我有以下代码:
public ActionResult SomeAction()
{
return new JsonpResult
{
Data = new { Widget = "some partial html for the widget" }
};
}
我想修改它以便我可以
public ActionResult SomeAction()
{
// will render HTML that I can pass to the JSONP result to return.
var partial = RenderPartial(viewModel);
return new JsonpResult
{
Data = new { Widget = partial }
};
}
这可能吗?有人可以解释一下吗?
注意,我在发布解决方案之前编辑了问题。
答案 0 :(得分:42)
我为ASP.NET MVC 4应用程序选择了以下扩展方法。我认为它比我见过的一些建议更简单:
public static class ViewExtensions
{
public static string RenderToString(this PartialViewResult partialView)
{
var httpContext = HttpContext.Current;
if (httpContext == null)
{
throw new NotSupportedException("An HTTP context is required to render the partial view to a string");
}
var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();
var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName);
var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller);
var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View;
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw);
}
}
return sb.ToString();
}
}
它允许我执行以下操作:
var html = PartialView("SomeView").RenderToString();
此外,此方法会保留视图的任何模型, ViewBag 和其他视图数据。
答案 1 :(得分:23)
这是一个有效的答案的略微修改版本:
public static string RenderPartialToString(string controlName, object viewData)
{
ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
viewPage.ViewData = new ViewDataDictionary(viewData);
viewPage.Controls.Add(viewPage.LoadControl(controlName));
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
viewPage.RenderControl(tw);
}
}
return sb.ToString();
}
用法:
string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model);
答案 2 :(得分:9)
DaveDev的回答对我来说效果很好,但是当局部视图调用另一个部分时,我得到“值不能为空。参数名称:视图”
搜索我已经制作了似乎运作良好的following的变体。
public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewDataDictionary ViewData = new ViewDataDictionary();
TempDataDictionary TempData = new TempDataDictionary();
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();
}
}
用法:
String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext)
答案 3 :(得分:7)
您可以创建将视图呈现为字符串的扩展名。
public static class RenderPartialToStringExtensions
{
/// <summary>
/// render PartialView and return string
/// </summary>
/// <param name="context"></param>
/// <param name="partialViewName"></param>
/// <param name="model"></param>
/// <returns></returns>
public static string RenderPartialToString(this ControllerContext context, string partialViewName, object model)
{
return RenderPartialToStringMethod(context, partialViewName, model);
}
/// <summary>
/// render PartialView and return string
/// </summary>
/// <param name="context"></param>
/// <param name="partialViewName"></param>
/// <param name="viewData"></param>
/// <param name="tempData"></param>
/// <returns></returns>
public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
{
return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
}
public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
{
ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partialViewName);
if (result.View != null)
{
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter output = new HtmlTextWriter(sw))
{
ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output);
result.View.Render(viewContext, output);
}
}
return sb.ToString();
}
return String.Empty;
}
public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, object model)
{
ViewDataDictionary viewData = new ViewDataDictionary(model);
TempDataDictionary tempData = new TempDataDictionary();
return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
}
}
然后在行动中使用它
[HttpPost]
public ActionResult GetTreeUnit(string id)
{
int _id = id.ExtractID();
string render = ControllerContext.RenderPartialToString("SomeView");
return Json(new { data = render });
}
答案 4 :(得分:2)
完美作品(仅限视图名称)
*对于参数,您可以使用模型
*也可以从视图中调用
查看旁边或主叫方
BuyOnlineCartMaster ToInvoice1 = new BuyOnlineCartMaster(); // for passing parameters
ToInvoice1.CartID = 1;
string HtmlString = RenderPartialViewToString("PartialInvoiceCustomer", ToInvoice1);
功能生成HTML
public static string RenderPartialViewToString(string viewName, object model)
{
using (var sw = new StringWriter())
{
BuyOnlineController controller = new BuyOnlineController(); // instance of the required controller (you can pass this as a argument if needed)
// Create an MVC Controller Context
var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
RouteData routeData = new RouteData();
routeData.Values.Add("controller", controller.GetType().Name
.ToLower()
.Replace("controller", ""));
controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
controller.ViewData.Model = model;
var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.ToString();
}
}
答案 5 :(得分:1)
同一主题的变体(mvc v1.0):
protected static string RenderPartialToString(Controller controller, string partialName, object model)
{
var vd = new ViewDataDictionary(controller.ViewData);
var vp = new ViewPage
{
ViewData = vd,
ViewContext = new ViewContext(),
Url = new UrlHelper(controller.ControllerContext.RequestContext)
};
ViewEngineResult result = ViewEngines
.Engines
.FindPartialView(controller.ControllerContext, partialName);
if (result.View == null)
{
throw new InvalidOperationException(
string.Format("The partial view '{0}' could not be found", partialName));
}
var partialPath = ((WebFormView)result.View).ViewPath;
vp.ViewData.Model = model;
Control control = vp.LoadControl(partialPath);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
return sb.ToString();
}
控制器内的使用:
public string GetLocationHighlites()
{
IBlockData model = WebPagesMapper.GetLocationHighlites();
// **this** being the controoler instance
// LocationPartial.ascx can be defined in shared or in view folder
return RenderPartialToString(**this**,"LocationPartial", model);
}
答案 6 :(得分:0)
您可以使用以下方式开箱即用:
var partial = new HtmlString(Html.Partial("_myPartial", Model).ToString());
答案 7 :(得分:0)
旧帖子,但我认为你让这太难了。
为什么不 return PartialView("<my partial>", model);
会返回您想要的字符串。
只需将 Get/Post 方法设为 IActionResult
作为 JsonResult
、PartialResult
和其他继承自 ActionResult,您可以发回任何内容,包括 JsonResult
[HttpPost]
public IActionResult CheckForContent(string id, string type){
try{
if(type = "something"){
return Json(new {
success = true,
myProp = "this prop"
});
} else {
MyViewModel model = new MyViewModel();
model.Content = _service.GetContent(new GetContentRequest(){ id = id }
return PartialView("<my partial>", model);
} catch(Exception ex){
_logger.LogError(ex.Message);
return Json(new { success = false }
}
}
阿贾克斯:
$.ajax({
url: '/CheckForContent',
type: 'POST',
cache: false,
contentType: false,
processData: false,
success: function (result) {
if(!result && !result.success){
console.log("Failed to load");
} else if(result && result.success){
$('#MyProp').val(result.myProp);
} else {
$('#MyContainer').html(result);
}
},
});