1.什么样的类能成为控制器?
在ASP.NET MVC 中,直接或者间接地实现了IController接口的类,就会被Mvc框架认为是控制器。
using System.Web.Routing; namespace System.Web.Mvc { public interface IController { void Execute(RequestContext requestContext); } }
从代码中,看到此接口有一个唯一的方法Execute,此方法会在请求到达控制器的时候被调用。
如果我们定义一个类实现直接实现此接口,也就意味着我们必须写大量的代码去处理请求。好在Mvc框架为我们定义一个Controller抽象类,我们直接可以此类派生,就可以获取到大量的处理请求的逻辑,我们只需要定义动作方法即可。
2.Mvc框架怎么知道需要用哪个控制器?
Mvc框架会从RouteData.Values中提取键为"controller"的值,这个值+“Controller”就组成了控制器的名称,也就是Mvc要找的那个控制器。
3. 控制器从哪些地方访问输入的数据?
主要是从三个地方: 1)通过上下文对象提取数据。 2)作为参数传给动作方法而形成的数据。3)明确的调用Mvc框架的模型绑定特性。
1)当我从Controller抽象类派生出自己的控制器时,我们就自动的得到了一批便利的属性,这些属性能够访问和请求相关的数据,这些对象有Request,Response,RouteData,HttpContext,Server.
2)① 使用动作方法参数,Mvc不允许动作方法有ref回out参数,Mvc遇到这个情况,就直接抛出异常。
② Mvc框架会帮我自动对动作方法进行赋值,而不需要我们手动检查上下文对象来赋值。 Mvc给动作方法赋值也是检查上下文对象来完成的。
这些上下文对象包括Request.QueryString,Request.Form和RouteData.Values。对参数的名称的处理是不区分大小的。比如动作方法的一个参数为city, 那么 Request.QueryString[“city”]或者Request.QueryString[“City”]都可以。
③ 参数对象怎么实例化的?底层的Controller类使用了叫“值提供器”和“模型绑定”的组件来为动作方法获取参数值。
④ 在Mvc框架中;如果找不到一个引用类型的参数的值,动作方法还会调用。不过这个参数的值被设置为null,可以说引用类型的参数是可选的。
如果动作方法的参数的类型是值类型,Mvc找不到这个参数的值,就会抛出异常。可以说值类型的参数是必须的。想让值类型的参数变成可选,
有2种方法:其一让参数义成可空类型。或者给参数设置默认值。
⑤ 如果不想处理不含动作方法参数值得请求,但又不想在代码中检查null或者抛出异常,可以使用C#的一个可选参数特性来代替:为参数指定默认。
public ActionResult Index(string query="All",int page=1) { //其他代码 }
3.控制器是怎么产生输出的?
Mvc框架通过使用“动作结果(Action Result)”把指明意图和执行意图分开。我们不是直接使用Response对象,而是返回一个派生于ActionResult类的对象。这个对象描述了控制器响应要完成的功能。例如渲染一个视图或者重定向到另一个URL或者动作方法等。
Mvc框架从一个动作方法接受到一个ActionResult对象时,Mvc框架就会调用由这个类所定义的ExecuteResult方。r然后改动作结果的实现处理Response对象,生成符合你意图的输出。
Mvc框架中有许多的内置的动作结果类型,这些类型都是派生于ActionResult,其中有不少类型在Controller类中有便利的方法。
---------
Mvc框架查找视图位置的顺序:
(应用程序使用了区域就从此处开始查找视图)
/Areas/<AreaName>/Views/<controllerName>/<ViewName>.aspx
/Areas/<AreaName>/Views/<controllerName>/<ViewName>.ascx
/Areas/<AreaName>/Views/Shared/<ViewName>.aspx
/Areas/<AreaName>/Views/Shared/<ViewName>.ascx
/Areas/<AreaName>/Views/<controllerName>/<ViewName>.cshtml
/Areas/<AreaName>/Views/<controllerName>/<ViewName>.vbhtml
/Areas/<AreaName>/Views/Shared/<ViewName>.cshtml
/Areas/<AreaName>/Views/Shared/<ViewName>.vbhtml
(应用程序没有使用区域就从此处开始查找,或者使用了区域,但早上面没有找到视图,就会接着道下面的地方查找)
/Views/<controllerName>/<ViewName>.aspx
/Views/<controllerName>/<ViewName>.ascx
/Views/Shared/<ViewName>.aspx
/Views/Shared/<ViewName>.ascx
/Views/<controllerName>/<ViewName>.cshtml
/Views/<controllerName>/<ViewName>.vbhtml
/Views/Shared/<ViewName>.cshtml
/Views/Shared/<ViewName>.cshtml
(ControllerName):控制器名称名称去掉"Controller"字符串之后的字符串。
①Mvc框架只要在一个位置查找到了视图,就会停止查找动作,而这个找到的视图便被用来把响应渲染给客户端。
②Mvc框架搜索视图的目录序列是“约定优于配置”。不需要注册视图文件,只需要你把视图文件放在一组已知的位置中,Mvc框架便可以识别他们。
③视图的实际名称是根据RouteData.Value["action"]的值所确定的。
④我们可以为View方法提供一个明确的路径并绕过搜索阶段来完成指定指定的视图。在指定一个视图时候,路径必须以“~/”或者“/”开始,并且包含文件的扩展名。
---------
怎么把数据从动作方法传递给视图。
⑴ 给视图提供一个模型对象。
可以把一个对象作为View方法的参数发送给视图。
public ViewResult Index() { DateTime dt=DateTime.Now; return View(dt); }
这样我们可以再视图中使用Model关键字访问此对象了。
⑵ 用ViewBag传递数据
该特性允许你在一个动态的对象上定义任何的属性,并在视图中访问它。
⑶ 使用ViewData传递数据
ViewData特性类似于View Bag特性,他是用ViewDataDictionary类实现的,而不是动态对象。
ViewDataDictionary类类似于规则的“键/值”集合。