如果动作是ajax或子动作,则返回部分视图

嗨,大家好我烧了谷歌试图构建某种类,如果它是AJAX调用或子动作或动作将确定UNIVERSALLY ,以便我的控制器可以确定是返回局部视图还是完整视图。 到目前为止,我没有多少运气。 目前我正在使用以下代码来实现这一目标

if (Request.IsAjaxRequest() || ControllerContext.IsChildAction) { return PartialView(); } return View(); 

问题是你必须在控制器中的每个动作和你遇到的每个条件中执行此操作但我确信有一种方法可以通过帮助程序实现这一点,但无法弄清楚如何。 你能指点我的任何链接/示例代码来实现这一点。

编辑:

@Aron我发布了一段代码,因为整个控制器太长了。 但你可以看到我的困境。 返回包含视图和对象/模型“k”。

 public ActionResult _Details_Message(int id = 0, int CId = 0) { ViewBag.MrnSortParm = CId; if (id != 0) { var k = mrn.MRNS.Where(u => u.Id == id).SingleOrDefault(); if (k.To == User.Identity.Name) { if (k.Type == 0) // message { k.Read = true; mrn.Entry(k).State = EntityState.Modified; mrn.SaveChanges(); } return PartialView("_Details_Message", k);//replace the above code here } if (k.From == User.Identity.Name) { return PartialView("_Sent", k); //replace the above code here } } var m = new message(); m.CourierId = CId; return PartialView("_Create_Message", m); //replace the above code here } 

编辑2我找到了答案,它不是辅助函数,而是视图中的修改。 链接在这里 。 可以将我自己的问题标记为重复:(

嗯,你很幸运,因为我写了一些TON代码来做类似的事情。 如果要将模型作为JSON对象或View返回,也会考虑这一点。 它还将所有Ajax调用包装到包装器响应元素中

基本上如果你有一个UI人做事,你永远不需要知道他想要什么。 让他写下观点,或者进行AJAX调用。 这完全将UI人员与C#开发人员分离(只要他理解如何编写MVC视图,他根本不需要知道控制器如何工作,只需知道传递的模型)。

ControllerBase类:

 public abstract class MyControllerBase : Controller { // could be moved to web.config private const _jsonDataType = "JsonDataType"; public bool IsAjaxRequest { get { return this.HttpContext.Request.IsAjaxRequest(); } } public bool IsAjaxHtmlRequest { get { return string.Equals(this.Request.Headers[MyControllerBase._jsonDataType], "html", StringComparison.CurrentCultureIgnoreCase); } } private JsonResponse GetAjaxResponse() { JsonResponse result = new JsonResponse(); result.IsValid = true; return result; } private JsonResponse GetAjaxResponse(T model) { JsonResponse result = new JsonResponse(); result.Data = model; result.IsValid = true; return result; } private JsonResponse GetAjaxHtmlResponse() { JsonResponse result = new JsonResponse(); result.Data = this.PartialViewToString(this.ControllerContext.RouteData.Values["Action"].ToString(), null); result.IsValid = true; return result; } private JsonResponse GetAjaxHtmlResponse(T model) { JsonResponse result = new JsonResponse(); result.Data = this.PartialViewToString(this.ControllerContext.RouteData.Values["Action"].ToString(), model); result.IsValid = true; return result; } private JsonResponse GetAjaxHtmlResponse(T model, string viewName) { JsonResponse result = new JsonResponse(); result.Data = this.PartialViewToString(viewName, model); result.IsValid = true; return result; } public ActionResult ViewOrAjax() { return this.ViewOrAjax(JsonRequestBehavior.DenyGet); } public ActionResult ViewOrAjax(JsonRequestBehavior jsonRequestBehavior) { if (this.ControllerContext.IsChildAction) { return this.PartialView(this.ControllerContext.RouteData.Values["Action"].ToString(), null); } if (this.IsAjaxRequest) { if (this.IsAjaxHtmlRequest) { return this.Json(this.GetAjaxHtmlResponse(), jsonRequestBehavior); } return this.Json(this.GetAjaxResponse(), jsonRequestBehavior); } return this.View(this.ControllerContext.RouteData.Values["Action"].ToString(), null); } public ActionResult ViewOrAjax(T model) { return this.ViewOrAjax(model, JsonRequestBehavior.DenyGet); } public ActionResult ViewOrAjax(T model, JsonRequestBehavior jsonRequestBehavior) { if (this.ControllerContext.IsChildAction) { return this.PartialView(model); } if (this.IsAjaxRequest) { if (this.IsAjaxHtmlRequest) { return this.Json(this.GetAjaxHtmlResponse(model), jsonRequestBehavior); } return this.Json(this.GetAjaxResponse(model), jsonRequestBehavior); } return this.View(model); } public ActionResult ViewOrAjax(IView view, T model, JsonRequestBehavior jsonRequestBehavior) { if (this.ControllerContext.IsChildAction) { return this.PartialView(model); } if (this.IsAjaxRequest) { if (this.IsAjaxHtmlRequest) { return this.Json(this.GetAjaxHtmlResponse(model), jsonRequestBehavior); } return this.Json(this.GetAjaxResponse(model), jsonRequestBehavior); } return this.View(view, model); } public ActionResult ViewOrAjax(string viewName, T model) { return this.ViewOrAjax(viewName, model, JsonRequestBehavior.DenyGet); } public ActionResult ViewOrAjax(string viewName, T model, JsonRequestBehavior jsonRequestBehavior) { if (this.ControllerContext.IsChildAction) { return this.PartialView(model); } if (this.IsAjaxRequest) { if (this.IsAjaxHtmlRequest) { return this.Json(this.GetAjaxHtmlResponse(model, viewName), jsonRequestBehavior); } return this.Json(this.GetAjaxResponse(model), jsonRequestBehavior); } return this.View(viewName, model); } public ActionResult ViewOrAjax(string viewName, string masterName, T model) { return this.ViewOrAjax(viewName, masterName, model, JsonRequestBehavior.DenyGet); } public ActionResult ViewOrAjax(string viewName, string masterName, T model, JsonRequestBehavior jsonRequestBehavior) { if (this.ControllerContext.IsChildAction) { return this.PartialView(model); } if (this.IsAjaxRequest) { if (this.IsAjaxHtmlRequest) { return this.Json(this.GetAjaxHtmlResponse(model, viewName), jsonRequestBehavior); } return this.Json(this.GetAjaxResponse(model), jsonRequestBehavior); } return this.View(viewName, masterName, model); } protected internal new ViewResult View(string viewName, string masterName, object model) { if (model != null) { ViewData.Model = model; } ViewResult result = new ViewResult { ViewName = viewName, MasterName = masterName, ViewData = ViewData, TempData = TempData }; return result; } } 

Ajax调用的JsonResponse<>全局包装器:

 public class JsonResponse { public JsonResponse() { } public bool IsValid { get; set; } public bool IsAjaxRequestUnsupported { get; set; } public string RedirectTo { get; set; } public string CanonicalUrl { get; set; } } public class JsonResponse : JsonResponse { public JsonResponse() : base() { } public T Data { get; set; } } 

Javascript global_getJsonResponse代码(需要jQuery):

 function global_getJsonResult(Controller, View, data, successCallback, completeCallback, methodType, returnType, jsonDataType) { if (IsString(Controller) && IsString(View) && !IsUndefinedOrNull(data)) { var ajaxData; var ajaxType; if (typeof (data) == "string") { ajaxData = data; ajaxType = "application/x-www-form-urlencoded" } else { ajaxData = JSON.stringify(data); ajaxType = "application/json; charset=utf-8"; } var method = 'POST'; if (methodType) { method = methodType; } var dataType = 'json'; if (returnType) { dataType = returnType; } var jsonType = 'html'; if (jsonDataType) { jsonType = jsonDataType; } var jqXHR = $.ajax({ url: '/' + Controller + '/' + View, headers: { JsonDataType: jsonType }, data: ajaxData, type: method, dataType: dataType, contentType: ajaxType, success: function (jsonResult) { if (!IsUndefinedOrNull(jsonResult) && jsonResult.hasOwnProperty("RedirectTo") && !IsUndefinedOrNull(jsonResult.RedirectTo) && jsonResult.RedirectTo.length > 0) { $.fn.notify('error', 'Login Expired', 'You have been inactive for a prolonged period of time, and have been logged out of the system.'); window.setTimeout(function () { window.location = jsonResult.RedirectTo }, 5000); } else if (IsFunction(successCallback)) { successCallback(jsonResult, Controller + '/' + View); } }, error: function (jqXHR, textStatus, errorThrown) { if (errorThrown != 'abort') { $.fn.notify('error', 'Whoops! Something went wrong.', 'We have been notified of the error.'/* textStatus + ': ' + errorThrown*/); } log('ERROR IN global_getJsonResult() : ', textStatus, errorThrown, jqXHR); }, complete: function (jqXHR, textStatus) { if (IsFunction(completeCallback)) { completeCallback(jqXHR, textStatus, Controller + '/' + View); } } }); return jqXHR; } } 

此代码通过在ajax调用中处理会话超时来支持服务器端和客户端TimeOut,其变化如下:

 protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult { Data = new JsonResponse { IsValid = false, RedirectTo = FormsAuthentication.LoginUrl }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { base.HandleUnauthorizedRequest(filterContext); } } 

在控制器上有两个扩展方法,允许你将渲染的部分视图作为文本返回到json(这段代码来自SO,我通常记录这些,但我丢失了它):

 internal static class ControllerExtensions { public static string PartialViewToString(this Controller instance, object model) { string viewName = instance.ControllerContext.RouteData.GetRequiredString("action"); return ControllerExtensions.PartialViewToString(instance, viewName, model); } public static string PartialViewToString(this Controller instance, string viewName, object model) { string result; ViewDataDictionary viewData = instance.ViewData; viewData.Model = model; using (var sw = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(instance.ControllerContext, viewName); var viewContext = new ViewContext(instance.ControllerContext, viewResult.View, viewData, instance.TempData, sw); viewResult.View.Render(viewContext, sw); viewResult.ViewEngine.ReleaseView(instance.ControllerContext, viewResult.View); result = sw.GetStringBuilder().ToString(); } return result; } } 

现在(遗憾地)从这个基本控制器派生所有控制器:

 public HomeController : MyBaseController { public ActionResult Index() { var viewModel = new MyViewModel(); return this.ViewOrAjax(viewModel); } } 

现在,如果浏览器调用页面作为标准获取,则可以使用Layout(也就是this.View(viewModel) )获取正常呈现的页面。

如果你通过Javascript使用Ajax调用它:

 global_getJsonResult("Home", // Controller or 'Area/Home' for areas "Index", // View $('#form').serialize(), // Json object or a serialized Form jsCallBack, // call back function or null "Post", // Get or Post "Html"); // "Html" to return a Partial View in "Data" // or "Json" to return a serialized view model in "Data" 

一个简单的解决方案可能是在Views文件夹下的_ViewStart.cshtml文件中使用类似的代码:

 @{ Layout = Request.IsAjaxRequest() || ViewContext.IsChildAction ? null : "~/Views/Shared/_Layout.cshtml"; } 

使用该代码,您只需return View(); 从你所有的行动。

由于所有视图都经过该步骤,这可能是您的通用解决方案。

对德米特里答案的改进:

创建一个自定义WebViewPage类,这样就不需要将修改添加到多个视图中(相关的地方有多个布局文件,这些文件由View本身而不是_ViewStart文件确定)

 public abstract class CustomWebViewPage: WebViewPage { public override string Layout { get { return Request.IsAjaxRequest() || ViewContext.IsChildAction ? null : base.Layout; } set { base.Layout = value; } } } public abstract class CustomWebViewPage: CustomWebViewPage { } 

并在web.config(在Views文件夹下)