ASP MVC 控制器没有被调用

4
为了更方便地进行单元测试,我正在尝试通过将数据访问功能移动到单独的存储库类中来实现存储库模式。
我的存储库中的数据访问类:
public class ErrorRepository : IErrorRepository
{
    public ErrorModel Errors { get; set; }
    public List<ErrorModel> ErrorList { get; set; }

    public List<ErrorModel> GetErrors()
    {
        string cs = "some path";

        using (SQLiteConnection con = new SQLiteConnection(cs))
        {
            var listOfErrors = new List<ErrorModel>();
            string stm = "SELECT * FROM Error WHERE Checked == 'False'";
            con.Open();

            using (SQLiteCommand cmd = new SQLiteCommand(stm, con))
            {
                using (SQLiteDataReader rdr = cmd.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        listOfErrors.Add(new ErrorModel
                        {
                            Id = rdr["ID"].ToString()
                        });
                    }

                    rdr.Close();
                    ErrorList = listOfErrors;
                }
            }

            con.Close();
        }

        return ErrorList;
    }
}

public interface IErrorRepository
{
    List<ErrorModel> GetErrors();
}

我的控制器:

public class ErrorController : Controller
{
    private IErrorRepository _errorRepository;

    public ErrorController(IErrorRepository errorRepository)
    {
        _errorRepository = errorRepository;
    }

    public ActionResult Error(int? page)
    {
        var errors = _errorRepository.GetErrors();

        //// stuff for paging
        int pageSize = 10;
        int pageNumber = (page ?? 1); // if there is no page, return page 1

        return View(errors.ToPagedList(pageNumber, pageSize));
    }
}

但问题是,控制器从未被调用。
我已经将其从之前的版本更改,其中控制器负责一切。所以我所做的一切就是将数据访问移出到一个单独的类中。错误视图与之前相同。我在实现中错过了一些细节吗?
更新:
我对构造函数进行了一些修改,并且有一些问题。为什么注入到构造函数中的以下代码无法工作:
    public ErrorController(IErrorRepository _errorRepository)
    {
        this._errorRepository = _errorRepository;
    }

但是,如果我把它改成这样,控制器就会被调用,一切似乎都正常工作:

    public ErrorController()
    {
        _errorRepository = new ErrorRepository();
    }

但是最后一个例子不是一个好的做法,因为ErrorController仍然与ErrorRepository紧密耦合吗?

更新2:

我创建了这个自定义控制器工厂:

public class ControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
            {
                throw new ArgumentNullException("controllerType");
            }
            if (!typeof (IController).IsAssignableFrom(controllerType))
            {
                throw new ArgumentException(string.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType");
            }
            return MvcUnityContainer.Container.Resolve(controllerType) as IController;
        }
        catch (Exception)
        {
            return null;
        }
    }
}

public static class MvcUnityContainer
{
    public static UnityContainer Container { get; set; }
}

还有这个引导类来设置所有依赖项:

public class Bootstrapper
{
    public static IUnityContainer Initialise()
    {
        var container = BuildUnityContainer();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
        container.RegisterType<IErrorRepository, ErrorRepository>();
        MvcUnityContainer.Container = container;

        return container;
    }
}

然后我在 Global.asax 文件中初始化它:

        // Initialise IoC container
        Bootstrapper.Initialise();
        // Register custom controller factory
        ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));

现在我可以使用构造函数注入,从而将我的ErrorController与ErrorRepository解耦:
    public ErrorController(IErrorRepository errorRepository)
    {
        this.errorRepository = errorRepository;
    }

2
你是否有某种能够注入 IErrorController 的 IoC?很可能因为你没有一个空的构造函数并且可能没有进行 DI 设置,所以它最终没有成功调用控制器。 - Johan
1
“控制器从未被调用”是什么意思?您发出了什么请求并获得了什么响应? - CodeCaster
1
针对你的更新,第一个方法没有起作用,因为你没有设置 DI 容器(如 Autofac、Ninject、Unity 等),来实际注入 ErrorRepository 的实例到 ErrorController 中,以满足对 IErrorRepository 的依赖。使用 DI 容器,你可以注册应该被用来满足依赖的类型,容器可以创建该类型的实例并提供给控制器。而且,第二种方式与 ErrorRepository 紧密耦合,应该避免,因为它无法隔离。 - mason
1
@Khaine775 这取决于你选择的 DI 容器。我使用过 Ninject,它有一个特殊的属性,可以在启动时注册它。对于其他容器,你可以在 global.asax 中添加一些内容。只需选择一个知名的 DI 容器,并查看他们的文档以了解如何注册它并设置依赖项即可。 - mason
1
既然您已经掌握了存储库模式,为什么不进一步实现服务模式呢?在服务模式中,所有逻辑都从控制器中取出并在服务中执行。该服务将业务逻辑与UI逻辑分离,并以与注入存储库相同的方式进行注入。此线程中的被接受答案是一个例子:http://codereview.stackexchange.com/questions/33109/repository-service-design-pattern - samneric
显示剩余5条评论
2个回答

0

好的,我通过阅读this关于如何使用Unity创建IoC的优秀文章来解决了这个问题。我已经更新了原始帖子并附上了我的最终代码。


0
在我的经验中,Ninject是一个不错的IoC容器。您可以从这里下载并运行我的ASP.NET MVC项目。我已经在从低级到高级的依赖注入中使用了它。希望这能让您了解Ninject框架以及我们为什么要遵循依赖反转原则。

你是指依赖注入原则还是控制反转原则?哈哈 - samneric
这是依赖倒置原则。它通过控制反转来实现。依赖注入是一种反转控制的方式,因此我们保持了依赖倒置原则。 :) - Yeasin Abedin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接