部分视图与Json(或两者)

我将ASP.NET MVC与jQuery一起使用,并且对我的控制器有很多Ajax请求。

使用部分视图(usercontrols)在加载页面时构建初始视图。 然后,如果我需要根据我的Ajax请求追加/替换数据,我会从Json响应中构建HTML。

这种方法让我完全掌控,即。 如果出现问题,我可以从我的控制器获取额外信息,然后根据该信息显示错误消息。

然而,最近我对在部分视图和从Json生成HTML的部分中维护HTML结构所做的所有额外工作感到非常恼火。

我想制作一个jQuery ajax请求,然后让控制器返回PartialView(“mypartialview”),然后只使用jQuery替换视图中的HTML。

但是,这样我就无法从控制器中附加额外的数据 – 无论是局部视图给我的是什么 – 或者什么都没有。 至少那是我目前的看法。

如果某些validation在我的控制器操作中的某个时刻出错,我不想返回局部视图的HTML。

那么你如何处理这个问题呢?

谢谢阅读。

基于这个 stackoverflow anwser,我刚刚开始做同样的事情。

首先为控制器类创建一个扩展方法。

public static string RenderViewToString(this Controller controller, string viewName, object model) { using (var writer = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); controller.ViewData.Model = model; var viewCxt = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, writer); viewCxt.View.Render(viewCxt, writer); return writer.ToString(); } } 

然后在controllers动作方法中返回json。

 return Json(new { Html = this.RenderViewToString("MyView", model), SomeExtraData = data }); 

你的ajax请求现在将收到包含在其中的html的json。 仍在尝试使用这种方法来返回普通的Html片段。

希望有所帮助。

编辑更新以使用剃刀

这是一种利用每个相应结果返回的Content-Type 。 我们使用它来发回错误信息,并且已经有JS用于显示消息,因此我们获得了我们想要的部分视图,或者用于错误报告等的控制信息。

作为参考,部分视图返回text/html ,JSON响应应该返回application/json

像往常一样,有趣的部分是在JavaScript方面,而JQuery ajax()在这里不会让人失望!

在您的控制器中,只需返回PartialView()Json(model,) ; 我们在try/catch格式中使用它。

 public ActionResult Edit(int id) { try { var model = getYourModel(); return PartialView("Edit", model); } catch (Exception ex) { var mi = new MessageInfo(MessageType.Error, String.Format("Edit failed: {0}", ex.Message), true); return Json(mi, "application/json", JsonRequestBehavior.AllowGet); } } 

在JS方面,我们使用以下function。 请注意,您需要从初始页面级GET重新建立您在$(document).ready()挂钩的任何JQuery事件,因此我们有一个回调参数。

 function getPartialView(action, controller, model, divId, callback) { var url = "/" + controller + "/" + action + "/"; $.ajax({ type: "GET", url: url, data: model, success: function (data, textStatus, jqXHR) { var ct = jqXHR.getResponseHeader("Content-Type"); var mx = ct.match("text\/html"); if (mx != null) { $(divId).html(data); if (callback) { callback($(divId)); } } else { addMessage(data.type, data.title, data.text, data.sticky); } }, error: function (jqXHR, textStatus, errorThrown) { addMessage(3, "\"" + url + "\": Failed", textStatus + ": " + errorThrown, false); } }); } 

唯一棘手的问题是检查响应中的Content-Type标头,并相应地执行操作。 请注意,如果不是HTML,我们假设JSON是“作弊”。 我们调用我们预先存在的addMessage()函数,做你需要的任何事情!

最后,这是一个示例Anchor元素,上面有onclick目标是getPartialView()

 Cancel 

作品很棒……

除了表单通过Ajax.BeginForm()提交,其中由于对Content-Typevalidation不充分,JSON有效负载被错误地视为HTML。 结果是你的div添加了一些JSON,它基本上不会呈现为HTML。 AjaxOptions.OnSuccess回调确实执行了,但是那时你的DOM为时已晚了!

有一个简单的解决方案,但不幸的是它需要对jquery-unobtrusive-ajax.js进行小修复 ,因为asyncOnSuccess()函数是短视的。

 function asyncOnSuccess(element, data, contentType) { var mode; if (contentType.indexOf("application/x-javascript") !== -1) { return; } if (contentType.indexOf("application/json") !== -1) { return; } ...snip... } 

在OOTB版本中,缺少第二个if语句; 添加它是必要的修复,以防止它将您的JSON有效负载抨击到DOM中。

有了这个修复程序,JSON有效负载将传递到您的AjaxOptions.OnSuccess Javascript中,您可以根据需要继续操作。

是的,你可以得到两个

希望你知道,因为你发送Json,你可以发回任何类型的模型,并让Javascript排序; hasOwnProperty()在那里派上用场。 很明显,您可以通过已经提到的RenderViewToString()发回一些视图HTML。

我相信你可以将渲染的html作为字符串返回 – 这可能是一个包含要显示的错误消息的html字符串?

你也可以这样做,把它放在你的控制器里面。

 protected string RenderPartialViewToString(string viewName, object model) { if (string.IsNullOrEmpty(viewName)) viewName = ControllerContext.RouteData.GetRequiredString("action"); ViewData.Model = model; using (StringWriter sw = new StringWriter()) { ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } }