Jac*_*ack 5 c# asp.net asp.net-core-mvc asp.net-core
我正在尝试使用 AJAX 来调用我的控制器并返回一个带有模型作为字符串的局部视图,以便我可以将它注入到我的 HTML 中。我之前在 MVC5 中使用控制器接口完成了此操作,但我似乎无法找到有关如何为 Asp.Net Core 2.2 中的部分视图执行此操作的任何信息。我找到了如何将视图呈现为字符串的示例,但我无法修改它们以适用于局部视图。
控制器动作:
public JsonResult GetUpsertPartialView(MessageBoard messageBoard)
{
Dictionary<string, string> result = new Dictionary<string, string>();
string errorState = "0";
string errorMessage = "";
try
{
result["view"] = ""; // My call to render the Partial View would go here.
}
catch (Exception)
{
errorState = "1";
errorMessage = "An error was encountered while constructing the View.";
}
result["errorState"] = errorState;
result["errorMessage"] = errorMessage;
return Json(result);
}
Run Code Online (Sandbox Code Playgroud)
AJAX 调用:
$.ajax({
type: "GET",
url: "../Home/GetUpsertPartialView/",
data: messageBoardData,
contentType: 'application/json; charset=utf-8',
success: function (data) {
console.log(data);
$("#messageBoardModalBody").val(data.view);
$("#messageBoardModal").modal("show");
}
});
Run Code Online (Sandbox Code Playgroud)
我已经确认我的控制器正在被命中,参数被正确传递,并且我正在从 Action 接收到正确的数据返回到我的 AJAX 调用。我唯一缺少的是将局部视图直接渲染为字符串的能力。
如果在 Asp.net Core 中有另一种方法可以做到这一点,我愿意接受其他选择。
注意:我这样做只是为了学习 Asp.Net Core。如果需要更多信息,请告诉我。
ControllerExtensions 实现
public static class ControllerExtensions
{
/// <summary>
/// Render a partial view to string.
/// </summary>
public static async Task<string> RenderViewToStringAsync(this Controller controller, string viewNamePath, object model = null)
{
if (string.IsNullOrEmpty(viewNamePath))
viewNamePath = controller.ControllerContext.ActionDescriptor.ActionName;
controller.ViewData.Model = model;
using (StringWriter writer = new StringWriter())
{
try
{
var view = FindView(controller, viewNamePath);
ViewContext viewContext = new ViewContext(
controller.ControllerContext,
view,
controller.ViewData,
controller.TempData,
writer,
new HtmlHelperOptions()
);
await view.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
catch (Exception exc)
{
return $"Failed - {exc.Message}";
}
}
}
private static IView FindView(Controller controller, string viewNamePath)
{
IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = null;
if (viewNamePath.EndsWith(".cshtml"))
viewResult = viewEngine.GetView(viewNamePath, viewNamePath, false);
else
viewResult = viewEngine.FindView(controller.ControllerContext, viewNamePath, false);
if (!viewResult.Success)
{
var endPointDisplay = controller.HttpContext.GetEndpoint().DisplayName;
if (endPointDisplay.Contains(".Areas."))
{
//search in Areas
var areaName = endPointDisplay.Substring(endPointDisplay.IndexOf(".Areas.") + ".Areas.".Length);
areaName = areaName.Substring(0, areaName.IndexOf(".Controllers."));
viewNamePath = $"~/Areas/{areaName}/views/{controller.HttpContext.Request.RouteValues["controller"]}/{controller.HttpContext.Request.RouteValues["action"]}.cshtml";
viewResult = viewEngine.GetView(viewNamePath, viewNamePath, false);
}
if (!viewResult.Success)
throw new Exception($"A view with the name '{viewNamePath}' could not be found");
}
return viewResult.View;
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器操作中的用法:
var html = await this.RenderViewToStringAsync("actionName" , model);
Run Code Online (Sandbox Code Playgroud)
可以使用服务从任何位置(控制器、页面模型等)获取部分视图(或多个):
这个答案的起源,他值得称赞(我在这里添加它是因为我需要类似的东西,并且我花了很长时间才找到它)
public interface IViewRenderService
{
Task<string> RenderToStringAsync(string viewName, object model);
}
Run Code Online (Sandbox Code Playgroud)
public class ViewRenderService : IViewRenderService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider;
public ViewRenderService(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
}
public async Task<string> RenderToStringAsync(string viewName, object model)
{
var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
using (var sw = new StringWriter())
{
var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);
if (viewResult.View == null)
{
throw new ArgumentNullException($"{viewName} does not match any available view");
}
var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = model
};
var viewContext = new ViewContext(
actionContext,
viewResult.View,
viewDictionary,
new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
sw,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return sw.ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
ConfigureServices:services.AddScoped<IViewRenderService, ViewRenderService>();
Run Code Online (Sandbox Code Playgroud)
string html = await m_RenderService.RenderToStringAsync("<NameOfPartial>", new Model());
Run Code Online (Sandbox Code Playgroud)
为什么 Json 结果带有 html 字符串?可以直接返回一个partial view来返回html。
public IActionResult GetUpsertPartialView(MessageBoard messageBoard)
{
return PartialView("someviewname", messageBoard);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5895 次 |
| 最近记录: |