ASP.NET MVC Framework体验(4):控制器

概述

在MVC中,Controller用来处理和回应用户的交互,选择使用哪个View来进行显示,需要往视图中传递什么样的视图数据等。ASP.NET MVC Framework中提供了IController接口和Controller基类两种类型,其中在Controller提供了一些MVC中常用的处理,如定位正确的action并执行、为action方法参数赋值、处理执行过程中的错误、提供默认的WebFormViewFactory呈现页面。IController只是提供了一个控制器的接口,如果用户想自定义一个控制器的话,可以实现IController,它的定义如下:

public interface IController
{
    void Execute(ControllerContext controllerContext);
}

定义控制器和action

在前面三篇的例子中,我们已经定义过了控制器,只要继承于Controller就可以了:

public class BlogController : Controller
{
    [ControllerAction]
    public void Index()
    {
        BlogRepository repository = new BlogRepository();

        List<Post> posts = repository.GetAll();
        RenderView("Index", posts);
    }

    [ControllerAction]
    public void New()
    { 
        RenderView("New");
    }
}
通过ControllerAction特性来指定一个方法为action,ControllerAction的定义非常简单:
[AttributeUsage(AttributeTargets.Method)]
public sealed class ControllerActionAttribute : Attribute
{
    public ControllerActionAttribute();
}

使用强类型传递ViewData

通过前面的一些示例,已经看到了一些示例如何从控制器传递视图数据给View,在Controller中,传递视图数据到View,我们可以有两种方式选择,其中一种是使用强类型来传递视图数据,如下示例代码:

[ControllerAction]
public void Index()
{
    BlogRepository repository = new BlogRepository();

    List<Post> posts = repository.GetAll();
    RenderView("Index", posts);
}

有朋友在回复中提到,如果想传递多个Model或者集合数据到View,该如何传递?这里需要再定义一个类型:

public class HomeViewData
{
    public List<Post> Posts
    {
        get; set;
    }

    public List<Category> Categories
    {
        get; set;
    }
}

然后在控制器中可以这样进行传递数据:

[ControllerAction]
public void Index()
{
    BlogRepository repository = new BlogRepository();
    List<Post> posts = repository.GetAll();

    List<Category> categories = repository.GetAllCategory();

    HomeViewData viewData = new HomeViewData();
    viewData.Posts = posts;
    viewData.Categories = categories;

    RenderView("Index", viewData);
}

使用强类型类来传递视图数据,有如下好处(来自于Scrottgu):

1.避免使用字符串来查询对象,得到对你的控制器和视图代码的编译时检查

2.避免需要在使用象C#这样的强类型语言中明确转换ViewData对象字典中的值

3.在你的视图网页的标识文件以及后台代码文件中得到你的ViewData对象的自动代码intellisense

4.可以使用代码重构工具来帮助自动化对整个应用和单元测试代码库的改动

使用ViewData字典来传递数据

在Controller基类中,有一个这样的字典定义:

public IDictionary<string, object> ViewData { get; }

这样我们可以直接把视图数据通过ViewData字段来传递,如下示例代码:

[ControllerAction]
public void Index()
{
    BlogRepository repository = new BlogRepository();
    List<Post> posts = repository.GetAll();

    List<Category> categories = repository.GetAllCategory();

    ViewData["posts"] = posts;
    ViewData["categories"] = categories;
    RenderView("Index");
}

在试图中,可以这样来获取视图数据:

<div>
    <%foreach (Post post in (ViewData["posts"] as List<Post>))
      { %>
    <div class="postitem">
        <strong>Title</strong><%=Html.Encode(post.Title) %></br>
        <strong>Author</strong><%=Html.Encode(post.Author) %></br>
        <strong>PubDate</strong><%=Html.Encode(post.PubDate.ToShortDateString()) %></br>
        <strong>Content</strong><%=Html.Encode(post.Description) %></br>
        <%=Html.ActionLink("Edit", new {action="Edit", Id=post.Id })%>
    </div><br />
    <% } %>
</div>

处理未知的Action

Controller类中包含了一个HandlerUnknownAction的方法:

protected internal virtual void HandleUnknownAction(string actionName);
它用来处理一些未知的Action,默认情况下将返回HTTP 404错误,如果想自定义该处理,可以覆写该方法:
[ControllerAction]
protected override void HandleUnknownAction(string actionName)
{
    if (ShouldShowSearch(action) == true)
    {
        RedirectToAction("search", new { query = action });
        return;
    }

    base.HandleUnknownAction(actionName);
}

它用来处理当出现未知的Action时,跳转向Search Action。

结束语

在本篇文章中,我们介绍了ASP.NET MVC Framework中的Controller,包括如何定义Controller及Action,通过强类型和视图数据字典来传递视图数据,以及自定义处理未知的Action等内容,希望对您有所帮助。最后,插播一条小广告:我在博客园社区中建立了一个Web技术联盟小组,欢迎大家加入:http://space.cnblogs.com/group/webdev/

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2007-12-14 21:07 TerryLee 阅读(4232) 评论(23)  编辑 收藏 网摘 所属分类: [08]  Web开发

  回复  引用  查看    
#1楼 2007-12-14 21:26 | yaosansi      
TerryLee的速度真快!
  回复  引用  查看    
#2楼 [楼主]2007-12-14 21:27 | TerryLee      
@yaosansi
呵呵,不快,争取一天一篇:)
  回复  引用  查看    
#3楼 2007-12-14 21:30 | Hafeyang      
收获不浅
刚好也回答了我在第一讲里提的问题
持续关注中
  回复  引用  查看    
#4楼 [楼主]2007-12-14 21:33 | TerryLee      
@Hafeyang
:)
  回复  引用  查看    
#5楼 2007-12-14 21:50 | 行知      
同MonoRail 确实有点类似,这样倒是降低了学习的成本
  回复  引用  查看    
#6楼 [楼主]2007-12-14 21:53 | TerryLee      
@行知
这只是开始,不过以MS的风格,应该不止于此,还会提供更加强大的功能
  回复  引用  查看    
#7楼 2007-12-14 22:16 | pk的眼泪      
不曾用过
  回复  引用  查看    
#8楼 [楼主]2007-12-14 22:21 | TerryLee      
@pk的眼泪
刚出来没几天
  回复  引用    
#9楼 2007-12-14 22:26 | je [未注册用户]
if (ShouldShowSearch(action) == true)
if (ShouldShowSearch(action))

  回复  引用  查看    
#10楼 [楼主]2007-12-14 22:31 | TerryLee      
@je
?
  回复  引用  查看    
#11楼 2007-12-14 22:57 | 没剑      
不知怎么始终还是喜欢monorail,感觉msmvc变得很是臃肿了
  回复  引用  查看    
#12楼 [楼主]2007-12-14 23:00 | TerryLee      
@没剑
现在还没有看出来臃肿在哪儿?:)
  回复  引用    
#13楼 2007-12-14 23:35 | o0myself0o [未注册用户]
@TerryLee
测试代码能发出来吗?
  回复  引用  查看    
#14楼 [楼主]2007-12-15 00:56 | TerryLee      
@o0myself0o
这个跟前几篇里的测试代码基本一样啊:)
  回复  引用  查看    
#15楼 2007-12-15 10:02 | 啊东      
多谢分享:)
  回复  引用  查看    
#16楼 2007-12-15 10:21 | songcan      
军哥厉害!不过要学的东西太多了,暂不考虑MSMVC,顺便提一下请不要忘了Smart Code,甚是期待啊!
  回复  引用  查看    
#17楼 2007-12-15 11:02 | Klesh Wong      
HomeViewData
咦 ,看到了传说中的VO
  回复  引用  查看    
#18楼 [楼主]2007-12-15 12:30 | TerryLee      
@啊东
:)
  回复  引用  查看    
#19楼 [楼主]2007-12-15 12:31 | TerryLee      
@songcan
一直在忙于开发啊,当然Blog更新也不能落下,呵呵
  回复  引用  查看    
#20楼 [楼主]2007-12-15 12:37 | TerryLee      
@Klesh Wong
呵呵:)
  回复  引用    
#21楼 2007-12-18 09:23 | TakWai [未注册用户]
有没检测未知的控制器方法?地址栏那里输入一个未知的控制器名称就出错了= =!

请教一下… 怎么用代码设置母版页那个标题?找了老半天没找到- -!
  回复  引用    
#22楼 2007-12-28 15:50 | lijing20012 [未注册用户]
<%foreach (Post post in (ViewData["posts"] as List<Post>))
{ %>
<div class="postitem">
<strong>Title</strong>:<%=Html.Encode(post.Title) %></br>
<strong>Author</strong>:<%=Html.Encode(post.Author) %></br>
<strong>PubDate</strong>:<%=Html.Encode(post.PubDate.ToShortDateString()) %></br>
<strong>Content</strong>:<%=Html.Encode(post.Description) %></br>
<%=Html.ActionLink("Edit", new {action="Edit", Id=post.Id })%>
</div><br />
<% } %>

这个风格什么时候能改变呀,感觉真不爽
  回复  引用    
#23楼 2008-02-03 23:37 | vler [未注册用户]
有个问题不会了,文件太多所以在controller, views中都加了二级目录UserManage;

views:
Views
|-UserManage //我加的那层目录
|-Users
|-List.aspx

controller:
namespace Mis.Controllers.UserManage
{
public class UsersController : Controller
{
[ControllerAction]
public void List()
{
RenderView("List");
}
}
}

Could not find an ASPX view '~/Views/Users/List.aspx'.
我自己加的UserManage不知道怎么由RenderView生成进url里面去。请问哪位遇到过类似问题?



标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-10-28 12:49 编辑过
Google站内搜索




相关链接: