控制器是各种操作的协调器,是位于模型与视图之间并在这两者之间传递数据的组件。
控制器的主要作用其实协调最终用户和应用程序。
控制器必须执行的任务是获取和验用户输入,将所有复杂的操作(业务逻辑规则和数据访问)委托给模型,并且在结果返回时确定使用哪个视图进行显示,并将数据传递所选择的数据。
控制器包含的内容越少越好,而将所有复杂的业务逻辑、数据访问以及数据操作都留给模型去处理。(MVC应用程序必须具有内容丰富的模型和内容少的控制器、以及一个哑视图)。
控制器类的唯一目的是作为动作的容器,是负责处理请求的地方。动作只是一个可以任意数量参数的公共方法,参数的数量可以零到多个,并且通常会返回System.Web.Mvc.ActionResult类型的对象。控制器通常在ViewData对象中设置需要传递到视图的数据,并通过View方法显示视图。
一.定义动作
通常情况下只需要在创建的控制器类中添加一个公共方法就可以创建一个动作,并且动作的名称就是方法的名称。但也可以通过一些特性修改默认行为。
用于控制动作定义的特性
- NonAction
- ActionName
- AcceptVerbs
- 创建自己的特性 Base ActionMethodSelectorAttribute
[AcceptVerbs("GET")]public ActionResult Update(){//ShowUpdateFormViewData["Message"] = "Welcome to the About Page with GET!";return View();}[AcceptVerbs("POST")]//[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]public ActionResult Update(FormCollection form){//ProcessUpdateFormViewData["Message"] = "Welcome to the About Page with POST!";return View();}[ActionName("View")]public ActionResult NotTheSameView(){ViewData["Title"] = "View Page";ViewData["Message"] = "Welcome to the View page from the method NotTheSameView";return View();}[NonAction]public void ThisIsNotAnAction(){//do some stuff}
二.向视图传递数据
动作的最终目标是收集数据并将数据返回给用户。大多数情况下,通过用于接收由动作检索到的数据视图完成的。可以通过三种不同的方法完成该工作:
- 使用ViewData对象
- 使用强类型的表示模型对象
- 使用TempData对象
三.请求检索数据
- 动作参数(url,post)
- 模型绑定
1.动作参数
url
public ActionResult Post(int year, int month, int day, string title, int commentId){ViewData["Message"] = String.Format("Title: {0}, day: {1}/{2}/{3}, commentId: {4}", title, month, day, year, commentId);return View();}
路由:
routes.MapRoute("NotSoDefault", // Route name"{controller}/{action}/{year}/{month}/{day}/{title}", // URL with parametersnew { controller = "Home", action = "Index", id = "" } // Parameter defaults);
url:http://localhost/blog/post/2012/08/30/title?commentId=8
post
public class BlogController: Controllers {public ActionResult Save(string postTitle, string postText){} }<form action="/post/save" method="post"> <input name="postTitle"/> <input name="postText"/> </form>
2.模型绑定
2.1.Bind特性:Prefix,Include,Exclude
asp.net mvc的默认绑定机制会尝试将html控件的值根据其名称映射到参数,在嵌套的对象之间导航,试着绑定整个层次的对象。
Controller:public ActionResult Save(User user, string pippo){return View("Save", user);}public ActionResult Save1([Bind(Prefix = "")]User user){return View("Save", user);}public ActionResult Save2([Bind(Include = "Username, Email")]User user){return View("Save", user);}public ActionResult Save3([Bind(Exclude = "Password")]User user){return View("Save", user);}public ActionResult Save4(){User user = new User();TryUpdateModel<IUserBindable>(user);return View("Save", user);}View:
<form action="/Home/Save4" method="post">UserName: <input type="text" id="username" name="Username" /><br />Email: <input type="text" id="email" name="Email" /><br />Country: <input type="text" id="country" name="HomeAddress.Country" /><br />City: <input type="text" id="city" name="HomeAddress.City" /><br />Street: <input type="text" id="street" name="HomeAddress.Street" /><br /><input type="submit" /></form>
2.2.在动作中绑定数据UpdateModel,TryUpdateModel
使用FormCollection绑定
// POST: /Movie2/Create [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(FormCollection collection) { var movieToCreate = new Movie(); this.UpdateModel(movieToCreate, collection.ToValueProvider()); // Insert movie into database return RedirectToAction(“Index”); }// POST: /Movie3/Create [AcceptVerbs(HttpVerbs.Post)] [ActionName(“Create”)] public ActionResult Create_POST() { var movieToCreate = new Movie(); this.UpdateModel(movieToCreate, new string[] {“Title”, “Director”,“DateReleased”});//这里可指定想要绑定的属性 // Add movie to database return RedirectToAction(“Index”); }
还可以定义一个具有允许绑定的属性接口:
public interface IUserBindable { string UserName {get;set;} string Email {get;set;} }public class User : IUserBindable { public string UserName {get;set;} public string Email {get;set;} public string Password{get;set;} }调用: UpdateModel<IUserBindable>(user);
使用http post 文件 HttpPostedFileBase 对象绑定
controller:[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(HttpPostedFileBase upload) { // Save file var fileName = Path.GetFileName(upload.FileName); upload.SaveAs(Server.MapPath(“~/Uploads/” + fileName)); return RedirectToAction(“Create”); }view:<form method=”post” enctype=”multipart/form-data” action=”<%= Url.Action(“Create”) %>”> <input name=”upload” type=”file” /> <input type=”submit” value=”Upload File” /> </form>
自定义模型绑定
namespace MvcApplication1.CustomModelBinders { public class UserModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return controllerContext.HttpContext.User; } } }
namespace MvcApplication1.Controllers { public class CompanyController : Controller { public string GetSecret([ModelBinder(typeof(UserModelBinder))] IPrincipal user) { if (user.Identity.Name == “CEO”) return “The secret is 42.”; else return “You are not authorized!”; } } }protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.Add(typeof(IPrincipal), new UserModelBinder()); }
四.动作结果类型
- ViewResult—Represents an ASP.NET MVC view.
- PartialViewResult—Represents a fragment of an ASP.NET MVC view.
- RedirectResult—Represents a redirection to another controller action or URL.
- ContentResult—Represents raw content sent to the browser.
- JsonResult—Represents a JavaScript Object Notation result (This is useful in Ajaxscenarios).
- FileResult—Represents a file to be downloaded.
- EmptyResult—Represents no result returned by an action.
- HttpUnauthorizedResult—Represents an HTTP Unauthorized status code.
- JavaScriptResult—Represents a JavaScript file.
- RedirectToRouteResult—Represents a redirection to another controller action or URL using route values.
- . View()—Returns a ViewResult
- . PartialView()—Returns a PartialViewResult
- . RedirectToAction()—Returns a RedirectToRouteResult
- . Redirect()—Returns a RedirectResult
- . Content()—Returns a ContentResult
- . Json()—Returns a JsonResult
- . File()—Returns a FileResult
- . JavaScript()—Returns a JavaScriptResult
- . RedirectToRoute()—Returns a RedirectToRouteResult
Returning a Redirect Result
public ActionResult Details(int? id) { if (!id.HasValue) return RedirectToAction(“Index”); return View(); }
Returning a Content Result
public ActionResult Say() { return Content(“Hello!”); }
Returning a JSON Result
public ActionResult List() { var quotes = new List<string> { “Look before you leap”, “The early bird gets the worm”, “All hat, no cattle” }; return Json(quotes); }view: <script type="text/javascript">$.ajaxSetup({ cache: false }); $(getQuote);function getQuote() { $.ajax({ url: "/Quotation/List", type: "POST", success: function (data) { var index = Math.floor(Math.random() * 3); $("#quote").text(data[index]); }, dataType:'json', error: function() { alert("请求失败"); } }); // $.getJSON("/Quotation/List", showQuote); }function showQuote(data) { var index = Math.floor(Math.random() * 3); $("#quote").text(data[index]); }</script><p id="quote"></p><button οnclick="getQuote()">Get Quote</button>
Returning a File Result
public ActionResult Download(){return File("~/Content/CompanyPlans.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "CompanyPlans.docx");}
public class FileNotFoundResult : ActionResult{public string Message { get; set; }public override void ExecuteResult(ControllerContext context) {throw new HttpException(404, Message);}}