问题描述
我一直在使用一种流行的SO帖子中的方法:How to render an ASP.NET MVC view as a string?
我没有将方法用作扩展方法,而是将其放在BaseController上,然后所有控制器都继承了base。这是我的实现:
public string RenderRazorViewToString(string viewName,object model = null)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,viewName);
var viewContext = new ViewContext(ControllerContext,viewResult.View,ViewData,TempData,sw);
viewResult.View.Render(viewContext,sw);
viewResult.ViewEngine.ReleaseView(ControllerContext,viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
它一直运行良好(我认为/希望),直到昨天。
我有一个JavaScript函数,可对控制器进行AJAX调用,并提供参数“ firstName”。控制器接受它,创建一个新的视图模型,设置FirstName属性,然后呈现模式(bootstrap3)局部视图。模态使用@Html.EditorFor
来呈现viewmodel的FirstName
属性。但是,该值不是由控制器上设置的显示文本,而是由Javascript传递的参数。本质上,当AJAX GET请求的参数与viewmodel中的属性名称匹配(不区分大小写)时,提供的参数优先。这是我一直在测试的代码:
function testModelBindingTempData() {
var $modalContainer = $('#modalContainer');
$.ajax({
url: "@Url.Action("GetTestModal")",method: "GET",data: {
firstName: "Michael is the bees knees."
},success: function(data) {
$modalContainer.html(data).find('.modal').modal('show');
},error: function(xhr,status,err) {
parseJsonHeaders(xhr,{ notificationLocation: '.notification-section' });
}
});
}
public JsonResult GetTestModal(string firstName)
{
TestModalviewmodel vm = new TestModalviewmodel();
vm.FirstName = "Michael is okay";
//just render and hope the best
return Json(RenderRazorViewToString("~/Views/Ajax/_TestModal.cshtml",vm));
}
@model Sample.Web.viewmodels.Ajax.TestModalviewmodel
<div class="modal modal-primary" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header"><span>Primary Simple Modal</span></div>
<div class="modal-body">
Used to inform the user of important stuff!
@Html.EditorFor(m => m.FirstName)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
结果:modal displays value supplied from the AJAX call instead of value set in the ViewModel
我发现问题值在ViewData.ModelState
键值对中,但我不知道为什么要设置该值,而不是在控制器和HTML帮助器中的表达式中设置的值。
我的期望是,当您在控制器中设置一个值时,它应该优先于模型状态值或任何其他可用数据。
有人知道为什么吗?任何建议表示赞赏,谢谢!
/ edit:经过额外的测试,这似乎也发生在常规的ActionResults / Views中。 :/
解决方法
这是预期的,因为您正在以下位置调用JSONResult:
public JsonResult GetTestModal(string firstName)
这是什么意思? ASP.NET MVC将使用JSON格式返回响应。如果要传递ViewData数据,请将其作为匿名对象的属性包含在JSONResult中,以便可以在AJAX成功处理程序中填充它:
Json(new { MyViewData = firstName },JsonRequestBehavior.AllowGet);
然后在AJAX成功处理程序上,您可以提取属性MyViewData
来填充HTML标记:
success: function(data) {
$modalContainer.html(data.MyViewData).find('.modal').modal('show');
},
如果要使用ViewBag,请不要使用JSONResult,而应使用ViewResult:
return View("ViewName",ModelName);