C# 为什么在ASP.NET MVC中首先运行控制器?

C# 为什么在ASP.NET MVC中首先运行控制器?,c#,asp.net-mvc,model-view-controller,asp.net-mvc-3,C#,Asp.net Mvc,Model View Controller,Asp.net Mvc 3,我想改进ASP.NET MVC框架的当前实现。 当前代码: routes.MapRoute(null, "I-want-to-fly", new { controller = "Airport", action = "Fly" }); public class AirportModel { public List<Plane> Planes { get; private set; } public List<Pilot> Pilots { get; pri

我想改进ASP.NET MVC框架的当前实现。 当前代码:

routes.MapRoute(null, "I-want-to-fly", new { controller = "Airport", action = "Fly" });

public class AirportModel 
{
   public List<Plane> Planes { get; private set; }
   public List<Pilot> Pilots { get; private set; }

   public void AddFly(Plane plane, Pilot pilot, Passenger passenger)
   {
        // . . .
   }
}

public class AirportController
{
   private AirportModel model;

   [HttpGet]
   public ViewResult Fly(string from, string to)
   {
       var planes = return (from p in model.Planes 
                            where p.CityFrom == from && p.CityTo == to
                            select p).ToList();
       return View(planes);
   }

   [HttpPost]
   public ActionResult Fly(Plane plane, Passenger passenger, DateTime time)
   {
       if (!(ModelState.IsValid && plane.TimeOfDeparture == time))
            return View();

       var pilot = (from p in model.Pilots 
                    where p.Free && p.CanAviate(plane.Id) 
                    select p).First();
       model.AddFly(plane, pilot, passenger);

       return RedirectToAction("Succeed");
   }
}
我的建议:

routes.MapRoute(null, "I-want-to-fly", new { model = "Airport", action = "Fly" });

public class AirportModel 
{
    private List<Plane> planes;
    private List<Pilot> pilots;

    private void AddFly(Plane plane, Pilot pilot, Passenger passenger)
    {
        // . . .
    }

    [HttpGet]
    public ViewResult Fly(string from, string to)
    {
        var planes = return (from p in model.Planes 
                             where p.CityFrom == from && p.CityTo == to
                             select p).ToList();
        return View(suitablePlanes);
    }

    [HttpPost]
    public ActionResult Fly(Plane plane, Passenger passenger, DateTime time)
    {
        if (!(ModelState.IsValid && new PlaneController().CanFly(plane, time)))
                return View();

        var pilot = (from p in pilots 
                     where p.Free && p.CanAviate(plane.Id) 
                     select p).First();
        AddFly(plane, pilot, passenger);

        return RedirectToAction("Succeed");
    }
}

public static class PlaneController
{
    public static bool CanFly(Plane plane, DateTime time)
    {
        return plane.TimeOfDeparture == time; // it will be more complex
    }
}
你看,这样我们就不需要过多的控制器和它们的方法。模型将仅通过perforce创建控制器:主要用于验证用户输入,而不是输入验证、业务验证

你认为这个想法能延续下去吗?或者,它有什么问题

谢谢你的回复

更新:我注意到,我们需要替换控制器和视图的实现,这主要是因为更改了模型的状态。所以,如果模型改变了实现,为什么模型不能这样做呢

更新2:在我看来,我解释错了。我不想让模特做所有的工作,当然不!我试着说,不是控制器应该决定对模型做什么,什么视图最适合这个用户请求

这难道不奇怪吗,这个模型不知道如何可视化自己,但一些控制器知道

这难道不奇怪吗,我们需要控制器来处理GET请求,在那里没有什么可以控制的

我试图消除这些奇怪的现象

更新3:我理解它不能应用于任何地方。主要的问题是:它能改进当前MVC实现的某些部分吗?我主要对ASP.NETMVC感兴趣-我们可以吗

删除冗余控制器或其某些方法 直接使用模型 使用这个想法?有可能吗?这个想法有什么问题

发现的问题:

模型和视图/控制器之间的联系更加紧密——但目前我认为这不是一个问题。实际上,它显示了视图和控制器是在主元素模型的帮助下创建的。
更新4:我更改了代码,显示before/after。也许这个例子会更好。

这难道不违背了我们的整体理念吗?模型与控制器和视图分离。以这种方式,您提出的方式将无法用另一个实现或控制器替换您的模型

更新一: 当然,你也可以让你的模型做控制器的一部分,但从那一刻起,你就不再谈论MVC设计模式了。对于MVC,模型现在应该也不应该关注视图。这就是管制员的工作

控制器接收用户输入并通过调用模型对象启动响应。控制器接受用户的输入,并指示模型和视口基于该输入执行操作

在MVC模式中,模型不仅仅固定在数据库模型上,它还可以是数据库模型和存储库模式的组合,您可以在其中实现业务逻辑

我看到你的建议的最大问题是它使代码不可重用。我得到了一个与视图紧密耦合的模型,如果我想以任何方式重用该模型,我真的不想这样做

更新二 我认为你被实际的文字控制者误导了,我有一段时间有这样的想法,你最近的评论某种程度上证实了这一点

控制器是一些对象,用于检查用户输入与业务逻辑的对应关系

控制器根据用户输入进行操作,他们可能会检查用户输入,但检查有效性的责任到此为止。业务逻辑再次出现在模型中,即MVC模式定义的模型,而不是datamodel中的模型。它们的主要目的是确定要显示的视图

另请参考您最近的一条评论:

您认为,如果[asp.net mvc]以我的方式开发,它会解决冗余控制器的问题吗

NETMVC遵循MVC设计模式。你的建议不可行。它看起来更像是一个模型控制的视图模式,只是为了给它起个名字。此外,没有冗余控制器,控制器没有问题,它们是解决方案的组成部分

通过一个代码示例简单地阐明我的意思:

namespace DataProject.Model
{
    public class AirportModel 
    {
        public List<Plane> Planes { get; set; }
        public List<Pilot> Pilots { get; set; }
        public List<Passenger> Passengers { get; set; }
        public List<Flight> Flights { get; set; }
    }

}

namespace SomeProject.Repository
{
    public class AirportRepository
    {
        private DataProject.Model.AirportModel model;

        //constructor sets the model somehow

        public bool AddFlight(Plane plane, List<Passenger> passengers, DateTime time)
        {
            //Business logic
            if (plane.TimeOfDeparture != time) return false;

            var pilot = (from p in model.Pilots 
                         where p.Free && 
                               p.CanAviate(plane.Id) 
                         select p).FirstOrDefault();
            //More Business logic
            if (pilot == null) return false;

            //Add plane, pilot and passenger to database
            model.Flights.add(new Flight{Pilot = pilot, Plane = plane, Passengers = passengers});
            //Even here you could decide to do some error handling, since you could get errors from database restrictions
            model.Save(); 

            return true;    
        }

        public List<Planes> GetPlanes(string from, string to)
        {
            return (from p in model.Planes 
                        where p.CityFrom == from && p.CityTo == to
                        select p).ToList();
        }
    }
}

namespace MVCApp.Controllers
{
    public class AirportController
    {
        private SomeProject.Repository.AirportRepository repository;

        [HttpGet]
        public ViewResult Fly(string from, string to)
        {
            var viewModel = repository.GetPlanes(from, to);
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Fly(Plane plane, List<Passenger> passengers, DateTime time)
        {
            if (!ModelState.IsValid) return View(); 

            if (!repository.AddFlight(plane, pilot, passenger)) return View();

           return RedirectToAction("Succeed");
        }
    }
}

这难道不是违背了我们的想法吗?模型与控制器和视图分离。以这种方式,您提出的方式将无法用另一个实现或控制器替换您的模型

更新一: 当然,你也可以让你的模型做控制器的一部分,但从那一刻起,你就不再谈论MVC设计模式了。对于MVC,模型现在应该也不应该关注视图。这就是管制员的工作

控制器接收用户输入并通过调用模型对象启动响应。控制器接受用户的输入,并指示模型和视口基于该输入执行操作

在MVC模式中,模型不仅仅是固定在数据库模型上的,它还可以是数据库模型和存储库模式的组合 实现您的业务逻辑

我看到你的建议的最大问题是它使代码不可重用。我得到了一个与视图紧密耦合的模型,如果我想以任何方式重用该模型,我真的不想这样做

更新二 我认为你被实际的文字控制者误导了,我有一段时间有这样的想法,你最近的评论某种程度上证实了这一点

控制器是一些对象,用于检查用户输入与业务逻辑的对应关系

控制器根据用户输入进行操作,他们可能会检查用户输入,但检查有效性的责任到此为止。业务逻辑再次出现在模型中,即MVC模式定义的模型,而不是datamodel中的模型。它们的主要目的是确定要显示的视图

另请参考您最近的一条评论:

您认为,如果[asp.net mvc]以我的方式开发,它会解决冗余控制器的问题吗

NETMVC遵循MVC设计模式。你的建议不可行。它看起来更像是一个模型控制的视图模式,只是为了给它起个名字。此外,没有冗余控制器,控制器没有问题,它们是解决方案的组成部分

通过一个代码示例简单地阐明我的意思:

namespace DataProject.Model
{
    public class AirportModel 
    {
        public List<Plane> Planes { get; set; }
        public List<Pilot> Pilots { get; set; }
        public List<Passenger> Passengers { get; set; }
        public List<Flight> Flights { get; set; }
    }

}

namespace SomeProject.Repository
{
    public class AirportRepository
    {
        private DataProject.Model.AirportModel model;

        //constructor sets the model somehow

        public bool AddFlight(Plane plane, List<Passenger> passengers, DateTime time)
        {
            //Business logic
            if (plane.TimeOfDeparture != time) return false;

            var pilot = (from p in model.Pilots 
                         where p.Free && 
                               p.CanAviate(plane.Id) 
                         select p).FirstOrDefault();
            //More Business logic
            if (pilot == null) return false;

            //Add plane, pilot and passenger to database
            model.Flights.add(new Flight{Pilot = pilot, Plane = plane, Passengers = passengers});
            //Even here you could decide to do some error handling, since you could get errors from database restrictions
            model.Save(); 

            return true;    
        }

        public List<Planes> GetPlanes(string from, string to)
        {
            return (from p in model.Planes 
                        where p.CityFrom == from && p.CityTo == to
                        select p).ToList();
        }
    }
}

namespace MVCApp.Controllers
{
    public class AirportController
    {
        private SomeProject.Repository.AirportRepository repository;

        [HttpGet]
        public ViewResult Fly(string from, string to)
        {
            var viewModel = repository.GetPlanes(from, to);
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Fly(Plane plane, List<Passenger> passengers, DateTime time)
        {
            if (!ModelState.IsValid) return View(); 

            if (!repository.AddFlight(plane, pilot, passenger)) return View();

           return RedirectToAction("Succeed");
        }
    }
}

您可以在一个类中做任何事情,而不需要控制器,但您需要考虑一些问题
因此,控制器负责http请求和验证,而模型只负责数据。

您可以在一个类中完成所有操作,而无需控制器,但您需要解决一些问题 因此,控制器负责http请求和验证,而模型只负责数据。

如果你是程序员,那么你可以同意或不同意MVC模式。 但是您描述的模式不支持关注点分离,它打破了关于MVC的整个想法

这与MVC无关

这是“MVNothing”

: 开玩笑吧,你是程序员,那么你可以同意或不同意MVC模式。 但是您描述的模式不支持关注点分离,它打破了关于MVC的整个想法

这与MVC无关

这是“MVNothing”

:
只是开玩笑而已*^

无意冒犯,但这究竟是一种什么样的进步

因此,您已经创建了一个名为PersonModel的类,它实际上根本不做模型的事情-它正在做控制器所做的工作-您已经让它处理GET和POST,并调用视图的显示,然后您就有了一个静态控制器,它实际上什么都不控制,只关心业务逻辑。老实说,我不明白这是什么进步

一个具体的例子是,您有一个控制器检查年龄是否大于等于18岁,这对于控制器来说是一个非常重要的业务规则。这不是控制器的目的。这就是模型对象的工作——关注业务逻辑之类的事情。控制器,更像是一个电子馆长。在你的例子中,你把它降到了比馆长低得多的地位


对象在MVC应用程序中扮演着不同的角色。视图向我们展示内容,并为我们提供与应用程序交互的方法。控制器处理来自视图的输入,并提供所需的视图。模型提供了一个放置数据以及模型包含的逻辑和业务规则的位置。服务处理诸如将数据持久化到某个存储区(如数据库)之类的事情。

无意冒犯,但这究竟是一种什么样的改进

因此,您已经创建了一个名为PersonModel的类,它实际上根本不做模型的事情-它正在做控制器所做的工作-您已经让它处理GET和POST,并调用视图的显示,然后您就有了一个静态控制器,它实际上什么都不控制,只关心业务逻辑。老实说,我不明白这是什么进步

一个具体的例子是,您有一个控制器检查年龄是否大于等于18岁,这对于控制器来说是一个非常重要的业务规则。这不是控制器的目的。这就是模型对象的工作——关注业务逻辑之类的事情。控制器,更像是一个电子馆长。在你的例子中,你把它降到了比馆长低得多的地位

对象在MVC应用程序中扮演着不同的角色。视图向我们展示内容,并为我们提供与应用程序交互的方法。控制器处理来自视图的输入,并提供所需的视图。模型提供了一个放置数据以及模型包含的逻辑和业务规则的位置。服务处理诸如将数据持久化到某个存储区(如数据库)之类的事情。

控制器不负责验证,这也是模型的工作。关于http请求

为什么是控制器?控制器需要控制一些东西,例如:用户输入,而不是解析路由…据我所知。@z0rch什么类型的验证?输入验证还是业务验证?@alexn业务验证。对于输入验证,我们将使用DataAnnotations。Controller不负责验证,这也是模型的工作。关于http请求-为什么选择控制器?控制器需要控制一些东西,例如:用户输入,而不是解析路由…据我所知。@z0rch什么类型的验证?输入验证还是业务验证?@alexn业务验证。对于输入验证,我们将使用数据注释。一切都是可能的,但它是否符合MVC模式。MVC模式规定了关注点的分离,其中每个字母表都有特定的功能要执行。例如,如果你的医生想驾驶飞机,他不需要成为飞行员,这是飞行员的工作,他只需要雇佣一名飞行员飞行员。@Mangeshpippalkar听着,如果模特医生想驾驶飞机,他会雇一名飞行员打电话给管制员。飞行员不选择医生,那么为什么管制员应该选择一个模型呢?医生不是模型,他是用户。飞机就是模型——飞行员管制员为工作选择模型中最好的飞机。“医生只关心到那里。”祖卡马尔,对不起,我说错了。飞行员和飞机都不是控制员。控制器是一些对象,用于检查用户输入与业务逻辑的对应关系。请看我更新的问题,我更新了code.hmmm,类似于FubuMvc的模型,不一样,但你可能会研究它所有的事情都是可能的,但它是否符合MVC模式。MVC模式说明了关注点的分离,每个字母表都有特定的功能要执行。例如,如果你的医生想驾驶飞机,他不需要成为飞行员,这是飞行员的工作,他只需要雇佣一名飞行员。@mangeshpippalkar听着,如果模特医生想驾驶飞机,他会雇佣一名飞行员呼叫管制员。飞行员不选择医生,那么为什么管制员应该选择一个模型呢?医生不是模型,他是用户。飞机就是模型——飞行员管制员为工作选择模型中最好的飞机。“医生只关心到那里。”祖卡马尔,对不起,我说错了。飞行员和飞机都不是控制员。控制器是一些对象,用于检查用户输入与业务逻辑的对应关系。请看我更新的问题,我更新了code.hmmm,类似于FubuMvc的模型,不一样,但你可能会研究一下。你经常重用没有视图和控制器的模型吗?在我看来,仅重用模型的能力在理论上是美好的,但在实践中并没有使用。也许我错了,因为我在生活中没有看到这样的例子。重用控制器或视图是另一回事,但在我的实现中我看不出它有什么问题。实际上,在很多情况下,后端与其他系统接口。为这些接口实现的服务根本不需要控制器,它们只是位于存储库之上,而存储库又位于数据模型之上。如果您的实现没有发现问题,那么您应该继续进行。没有人有理由告诉你停止做你正在做的事情。但它不是MVC设计模式的改进版本。对不起,我不理解你的例子。您的控制器是否封装了业务逻辑?如果没有,开发它们的目的是什么?仅用于将请求委托给维基百科中所述的模型?我建议创建内部控制器——它们将为模型保存一些业务逻辑。然后,当您与这个模型交互时,您的所有请求都将在控制器的帮助下得到验证——但作为模型的用户,您将不知道控制器是否存在。在这种情况下,您不需要外部控制器——当您可以安全地直接使用模型时,为什么呢?我的控制器验证用户输入,然后从其中一个存储库中检索数据,然后在从数据上下文检索数据时应用业务逻辑。然后相应地显示一个视图;B在向数据上下文添加、更新或删除数据之前,将数据传递到应用业务逻辑的存储库之一。如果我的模型中有某种控制器,即存储库或数据上下文,它们将如何帮助我的后端服务(例如写入MSMQ)?那我就不需要额外的行李了。好吧,我同意你的看法——哪里都不好。让我们回到ASP.NET MVC框架。你们认为,若按照我的方式开发,它将如何解决冗余控制器的问题?除了元素之间更紧密的联系外,它还有什么新问题?另外,我想对你说:谢谢你的宝贵意见!您是否经常重用没有视图和控制器的模型?在我看来,仅重用模型的能力在理论上是美好的,但在实践中并没有使用。也许我错了,因为我没有看到这样的情况
我生活中的例子。重用控制器或视图是另一回事,但在我的实现中我看不出它有什么问题。实际上,在很多情况下,后端与其他系统接口。为这些接口实现的服务根本不需要控制器,它们只是位于存储库之上,而存储库又位于数据模型之上。如果您的实现没有发现问题,那么您应该继续进行。没有人有理由告诉你停止做你正在做的事情。但它不是MVC设计模式的改进版本。对不起,我不理解你的例子。您的控制器是否封装了业务逻辑?如果没有,开发它们的目的是什么?仅用于将请求委托给维基百科中所述的模型?我建议创建内部控制器——它们将为模型保存一些业务逻辑。然后,当您与这个模型交互时,您的所有请求都将在控制器的帮助下得到验证——但作为模型的用户,您将不知道控制器是否存在。在这种情况下,您不需要外部控制器——当您可以安全地直接使用模型时,为什么呢?我的控制器验证用户输入,然后从其中一个存储库中检索数据,然后在从数据上下文检索数据时应用业务逻辑。然后相应地显示一个视图;B在向数据上下文添加、更新或删除数据之前,将数据传递到应用业务逻辑的存储库之一。如果我的模型中有某种控制器,即存储库或数据上下文,它们将如何帮助我的后端服务(例如写入MSMQ)?那我就不需要额外的行李了。好吧,我同意你的看法——哪里都不好。让我们回到ASP.NET MVC框架。你们认为,若按照我的方式开发,它将如何解决冗余控制器的问题?除了元素之间更紧密的联系外,它还有什么新问题?另外,我想对你说:谢谢你的宝贵意见!