ASP.NET MVC . Controller
20895 ワード
Controllerは、さまざまなタイプのActionResultを返す多くの方法を提供しています.
1.Viewで最も一般的な1つで、「標準」ページを返すことができます.
このページのデフォルトはViewPageです.また、独自に定義した他のテンプレートエンジンページでもあります.MVCはまた、強いタイプのViewPageを提供している.
Index.aspx
WebForm時代には、1つのページを複数のUserControlに分解することに慣れていましたが、今でもそうすることができます.htmlHelperはRenderPartialの拡張方法を専門に提供し、現在のビューディレクトリ(Viewsxxx)からダウンロードした.ascxページ.
RenderPartialInternalはFindParitialViewを呼び出してビューエンジンからロードする.ascxは、現在の環境パラメータを渡します.つまり、RenderPartialはビューレベルの動作にすぎず、Controller Action操作が再びトリガーされることはない.PartialView()は区別されます.Index.aspx
Part.ascx
2.ContentContentは、出力(Response.Write)「静的」フラグメントに使用されます.
jQueryとの組み合わせを見てみましょう.
Index.aspx
3. PartialViewController.PartialView()とHtmlHelper.RenderPartial()の違いは、前者がActionInvokeを再実行し、既存のViewContextを使用してビュークリップを表示するだけのActionResult結果を返すことです.ControllerとContent()の違いは、PartialView()がビューエンジンを使用して「動的」なascx結果を出力することです.
Content()と同様に、通常jQueryなどのAjaxフレームワークと組み合わせて使用します.
Index.aspx
Part.ascx
4.Redirect/RedirectToAction/RedirectToRouteControllerは、異なるAction間でジャンプする方法をいくつか提供しています.
方法1:Redirect()をそのままResponse.Redirect()urlジャンプを完了します.
詳細:
方法2:RedirectToAction()は、直接ActionNameを使用してジャンプします.
ターゲットアクションが現在のControllerクラスにない場合は、ターゲットController Nameを指定できます.
詳細:
RedirectToRouteResultが見えます.ExecuteResultではRoute関連情報をターゲットUrlにつなぎ合わせてジャンプする.方法3:RedirectToRoute()はMapRouteで直接定義したRoute Nameでジャンプする.
詳細:
実行プロセスはRedirectToAction()と同じです.5.JsonJson()は、Ajaxを作成するときに非常に役立ち、EntityなどのオブジェクトをJSON形式にシーケンス化してJavascriptで使用することができます.
Index.aspx
使いやすいですね.詳細を見てください.
Systemを使用します.Web.Script.Serialization.JavaScriptSerializerはJSONシーケンス化を完了します.つまり、ScriptIgnoreAttributeでいくつかの属性を除外することもできます.6.Javascript時々、いくつかの論理判断に基づいて異なるJavascriptコードをロードする必要があります.
Index.aspx
ただ、このやり方では、ViewとControllerの結合が大きくなっているようですが・・・むしろJavascriptで直接処理したほうがいいです.
7.File(Download/Upload)File()は、Download機能を提供します.
ブラウザで「/Test/Download/1」を要求すると、ダウンロードウィンドウが開き、保存ファイル名が与えられます.
ファイルアップロードはもう一つの一般的なWebアプリケーションです.
Index.aspx
MVCはHttpPostedFileBaseModelBinderがRequestを提供する.Filesの情報はActionの同名パラメータに直接マッピングされます.
複数のファイルを一度にアップロードするデモを見てみましょう.
Index.aspx
[最終修正
1.Viewで最も一般的な1つで、「標準」ページを返すことができます.
protected internal virtual ViewResult View(string viewName, string masterName, object model){ if (model != null) { base.ViewData.Model = model; } return new ViewResult { ViewName = viewName, MasterName = masterName, ViewData = base.ViewData, TempData = base.TempData };}public class ViewResult : ViewResultBase{ protected override ViewEngineResult FindView(ControllerContext context) { ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName); if (result.View != null) { return result; } ... }}
このページのデフォルトはViewPageです.また、独自に定義した他のテンプレートエンジンページでもあります.MVCはまた、強いタイプのViewPage
public class User{ public string Name { get; set; } public int Age { get; set; }}public class TestController : Controller{ public ActionResult Index() { ViewData["message"] = "Hello, World!"; var model = new User { Name = "Tom", Age = 13 }; return View(model); }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Learn.MVC.Controllers.User>" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title></head><body> Name: <%= Model.Name %>; Age: <%= Model.Age %></body></html>
WebForm時代には、1つのページを複数のUserControlに分解することに慣れていましたが、今でもそうすることができます.htmlHelperはRenderPartialの拡張方法を専門に提供し、現在のビューディレクトリ(Viewsxxx)からダウンロードした.ascxページ.
public static class RenderPartialExtensions{ public static void RenderPartial(this HtmlHelper htmlHelper, partialViewName, model, viewData) { htmlHelper.RenderPartialInternal(partialViewName, viewData, model, ViewEngines.Engines); }}public class HtmlHelper{ internal virtual void RenderPartialInternal(string partialViewName, ViewDataDictionary viewData, object model, ViewEngineCollection viewEngineCollection) { ... ViewDataDictionary newViewData = null; if (model == null) { if (viewData == null) newViewData = new ViewDataDictionary(ViewData); else newViewData = new ViewDataDictionary(viewData); } else { if (viewData == null) newViewData = new ViewDataDictionary(model); else newViewData = new ViewDataDictionary(viewData) { Model = model }; } ViewContext newViewContext = new ViewContext(ViewContext, ViewContext.View, newViewData, ViewContext.TempData); IView view = FindPartialView(newViewContext, partialViewName, viewEngineCollection); view.Render(newViewContext, ViewContext.HttpContext.Response.Output); } internal static IView FindPartialView(viewContext, partialViewName, viewEngineCollection) { ViewEngineResult result = viewEngineCollection.FindPartialView(viewContext, partialViewName); if (result.View != null) { return result.View; } ... }}
RenderPartialInternalはFindParitialViewを呼び出してビューエンジンからロードする.ascxは、現在の環境パラメータを渡します.つまり、RenderPartialはビューレベルの動作にすぎず、Controller Action操作が再びトリガーされることはない.PartialView()は区別されます.Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Learn.MVC.Controllers.User>" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title></head><body> Name: <%= Model.Name %>; Age: <%= Model.Age %> <br /> <% Html.RenderPartial("Part"); %></body></html>
Part.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Learn.MVC.Controllers.User>" %><%= ViewData["message"] %> <br /><%= Model.Name %>
2.ContentContentは、出力(Response.Write)「静的」フラグメントに使用されます.
protected internal virtual ContentResult Content(content, contentType, contentEncoding){ return new ContentResult { Content = content, ContentType = contentType, ContentEncoding = contentEncoding };}public class ContentResult : ActionResult{ public string Content { get; set; } public override void ExecuteResult(ControllerContext context) { ... HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Content != null) { response.Write(Content); } }}
jQueryとの組み合わせを見てみましょう.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult Part() { return Content("<a href=\"http://www.rainsts.net\">Q.yuhen</a>"); }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title> <script src="http://www.cnblogs.com/Scripts/jquery-1.3.1.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#div1").load("/test/part"); }); </script></head><body> <div id="div1"> </div></body></html>
3. PartialViewController.PartialView()とHtmlHelper.RenderPartial()の違いは、前者がActionInvokeを再実行し、既存のViewContextを使用してビュークリップを表示するだけのActionResult結果を返すことです.ControllerとContent()の違いは、PartialView()がビューエンジンを使用して「動的」なascx結果を出力することです.
protected internal virtual PartialViewResult PartialView(string viewName, object model){ if (model != null) { ViewData.Model = model; } return new PartialViewResult { ViewName = viewName, ViewData = ViewData, TempData = TempData };}public class PartialViewResult : ViewResultBase{ protected override ViewEngineResult FindView(ControllerContext context) { ViewEngineResult result = ViewEngineCollection.FindPartialView(context, ViewName); if (result.View != null) { return result; } ... }}
Content()と同様に、通常jQueryなどのAjaxフレームワークと組み合わせて使用します.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult Part() { ViewData["time"] = DateTime.Now; var model = new User { Name = "Tom", Age = 13 }; return PartialView(model); }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title> <script src="http://www.cnblogs.com/Scripts/jquery-1.3.1.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#div1").load("/test/part"); }); </script></head><body> <div id="div1"> </div></body></html>
Part.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Learn.MVC.Controllers.User>" %><%= ViewData["time"] %> <br /><%= Model.Name %>; <%= Model.Age %>
4.Redirect/RedirectToAction/RedirectToRouteControllerは、異なるAction間でジャンプする方法をいくつか提供しています.
public class MvcApplication : System.Web.HttpApplication{ public static void RegisterRoutes(RouteCollection routes) { ... routes.MapRoute ( "Test2", "Test/T2/{name}/{age}", new { controller = "Test", action = "T2", name = "", age = 0 } ); ... }}
方法1:Redirect()をそのままResponse.Redirect()urlジャンプを完了します.
public class TestController : Controller{ public ActionResult Index() { return Redirect("/Test/T2/Tom/23"); } public ActionResult T2(User user) { return Content(user.Name); }}
詳細:
protected internal virtual RedirectResult Redirect(string url){ ... return new RedirectResult(url);}public class RedirectResult : ActionResult{ public override void ExecuteResult(ControllerContext context) { ... string destinationUrl = UrlHelper.Content(Url, context.HttpContext); context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */); }}
方法2:RedirectToAction()は、直接ActionNameを使用してジャンプします.
public class TestController : Controller{ public ActionResult Index() { return RedirectToAction("T2", new { name = "Tom", age = 23 }); } public ActionResult T2(User user) { return Content(user.Name); }}
ターゲットアクションが現在のControllerクラスにない場合は、ターゲットController Nameを指定できます.
return RedirectToAction("T2", new { controller="Test2", name = "Tom", age = 23 });
詳細:
protected internal virtual RedirectToRouteResult RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues){ RouteValueDictionary mergedRouteValues; if (RouteData == null) { mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, null, routeValues, true /* includeImplicitMvcValues */); } else { mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, RouteData.Values, routeValues, true /* includeImplicitMvcValues */); } return new RedirectToRouteResult(mergedRouteValues);}public class RedirectToRouteResult : ActionResult{ public override void ExecuteResult(ControllerContext context) { ... string destinationUrl = UrlHelper.GenerateUrl(RouteName, null /* actionName */, null /* controllerName */, RouteValues, Routes, context.RequestContext, false /* includeImplicitMvcValues */); ... context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */); }}
RedirectToRouteResultが見えます.ExecuteResultではRoute関連情報をターゲットUrlにつなぎ合わせてジャンプする.方法3:RedirectToRoute()はMapRouteで直接定義したRoute Nameでジャンプする.
public class TestController : Controller{ public ActionResult Index() { return RedirectToRoute("Test2", new { name = "Tom", age = 23 }); }}
詳細:
protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName, RouteValueDictionary routeValues){ return new RedirectToRouteResult(routeName, RouteValuesHelpers.GetRouteValues(routeValues));}
実行プロセスはRedirectToAction()と同じです.5.JsonJson()は、Ajaxを作成するときに非常に役立ち、EntityなどのオブジェクトをJSON形式にシーケンス化してJavascriptで使用することができます.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult GetUser(string name) { var user = new User { Name = name, Age = 23 }; return Json(user); }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title> <script src="http://www.cnblogs.com/Scripts/jquery-1.3.1.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#btnTest").click(function() { $.getJSON ( "/Test/GetUser", { name: "Tom" }, function(json) { alert(json.Name + ";" + json.Age); } ); }); }); </script></head><body> <input type="button" id="btnTest" value="Test" /></body></html>
使いやすいですね.詳細を見てください.
protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding){ return new JsonResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding };}public class JsonResult : ActionResult{ public override void ExecuteResult(ControllerContext context) { ... if (Data != null) { JavaScriptSerializer serializer = new JavaScriptSerializer(); response.Write(serializer.Serialize(Data)); } }}
Systemを使用します.Web.Script.Serialization.JavaScriptSerializerはJSONシーケンス化を完了します.つまり、ScriptIgnoreAttributeでいくつかの属性を除外することもできます.6.Javascript時々、いくつかの論理判断に基づいて異なるJavascriptコードをロードする必要があります.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult GetJs(int id) { switch (id) { case 1: return JavaScript("alert('Hello, C#!');"); case 2: return JavaScript("alert('Hello, MVC!');"); default: return null; } }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title> <script src="http://www.cnblogs.com/Scripts/jquery-1.3.1.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#btnTest").click(function() { var id = $("#txtId").val(); $.getScript("/Test/GetJs/" + id); }); }); </script></head><body> <input type="text" id="txtId" value="1" /> <input type="button" id="btnTest" value="Test" /></body></html>
ただ、このやり方では、ViewとControllerの結合が大きくなっているようですが・・・むしろJavascriptで直接処理したほうがいいです.
protected internal virtual JavaScriptResult JavaScript(string script){ return new JavaScriptResult { Script = script };}public class JavaScriptResult : ActionResult{ public override void ExecuteResult(ControllerContext context) { ... HttpResponseBase response = context.HttpContext.Response; response.ContentType = "application/x-javascript"; if (Script != null) { response.Write(Script); } }}
7.File(Download/Upload)File()は、Download機能を提供します.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult Download(int id) { var filename = String.Format("~/Content/Download/{0}.rar", id); var fileDownloadName = String.Format("{0}.rar", id); return File(filename, "application/octet-stream", fileDownloadName); }}
ブラウザで「/Test/Download/1」を要求すると、ダウンロードウィンドウが開き、保存ファイル名が与えられます.
protected internal virtual FileContentResult File(byte[] fileContents, contentType, fileDownloadName){ return new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName };}public abstract class FileResult : ActionResult{ public override void ExecuteResult(ControllerContext context) { ... HttpResponseBase response = context.HttpContext.Response; response.ContentType = ContentType; ... WriteFile(response); } protected abstract void WriteFile(HttpResponseBase response);}public class FileContentResult : FileResult{ protected override void WriteFile(HttpResponseBase response) { response.OutputStream.Write(FileContents, 0, FileContents.Length); }}
ファイルアップロードはもう一つの一般的なWebアプリケーションです.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult Upload(HttpPostedFileBase file) { var filename = Server.MapPath("~/Content/Upload/" + Path.GetFileName(file.FileName)); file.SaveAs(filename); return null; }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title></head><body> <form action="/Test/Upload" enctype="multipart/form-data" method="post"> <input type="file" name="file" /> <input type="submit" name="upload" /> </form></body></html>
MVCはHttpPostedFileBaseModelBinderがRequestを提供する.Filesの情報はActionの同名パラメータに直接マッピングされます.
public class HttpPostedFileBaseModelBinder : IModelBinder{ public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ... HttpPostedFileBase theFile = controllerContext.HttpContext.Request.Files[bindingContext.ModelName]; // case 1: there was no <input type="file" ... /> element in the post if (theFile == null) { return null; } // case 2: there was an <input type="file" ... /> element in the post, but it was left blank if (theFile.ContentLength == 0 && String.IsNullOrEmpty(theFile.FileName)) { return null; } // case 3: the file was posted return theFile; }}
複数のファイルを一度にアップロードするデモを見てみましょう.
public class TestController : Controller{ public ActionResult Index() { return View(); } public ActionResult Upload(HttpPostedFileBase file1, HttpPostedFileBase file2) { var html = String.Format("{0}:{1}<br />{2}:{3}", file1.FileName, file1.InputStream.Length, file2.FileName, file2.InputStream.Length); return Content(html); }}
Index.aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Index</title></head><body> <form action="/Test/Upload" enctype="multipart/form-data" method="post"> <input type="file" name="file1" /> <input type="file" name="file2" /> <input type="submit" name="upload" /> </form></body></html>
[最終修正