使用ASP.NET Core 2表单输入验证的Razor视图字符串

时间:2017-12-02 22:12:13

标签: c# asp.net-mvc asp.net-core asp.net-core-2.0

我使用.NET核心2.我找到了渲染razor视图到字符串的解决方案。较低的MVC版本我已经使用它并且everthing没问题。 我得到结果/形式到bootstrap模态。当我发布到控制器(ex UserName空值)时,我无法从ModelState获得<span asp-validation-for="UserName" class="text-danger"></span>的结果,哪里有问题? 当我不使用RenderToStringAsync方法和return View()时,我会从ModelState获得<span asp-validation-for="UserName" class="text-danger"></span>的结果。 始终actionContext ModelState值或键也为空。

我的服务器端:

  public class RazorViewToStringRenderer
    {
        private readonly IRazorViewEngine viewEngine;
        private readonly ITempDataProvider tempDataProvider;
        private readonly IHttpContextAccessor _httpContext;

        public RazorViewToStringRenderer(
            IRazorViewEngine viewEngine,
            ITempDataProvider tempDataProvider,
            //IServiceProvider serviceProvider,
            IHttpContextAccessor httpContext)
        {
            this.viewEngine = viewEngine;
            this.tempDataProvider = tempDataProvider;
            _httpContext = httpContext;
        }

        public async Task<string> RenderToStringAsync(string viewName, object model)
        {
            var httpContext = _httpContext.HttpContext;
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            using (var sw = new StringWriter())
            {
                var viewResult = viewEngine.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()
                    )
                { RouteData = httpContext.GetRouteData() };


                await viewResult.View.RenderAsync(viewContext);
                return sw.ToString();
            }
        }
    } 

客户端:

@model EditUserViewModel

        <form asp-controller="Account" asp-action="EditUser" asp-antiforgery="true" data-ajax-success="onSuccess" data-ajax="true" data-ajax-begin="onBegin" method="post" class="form-horizontal" role="form">
    ....
            <div class="form-group">
                <div class="col-sm-12">
                    <label asp-for="UserName" class="col-form-label"></label>
                    <input asp-for="UserName" class="form-control" />
                    <span asp-validation-for="UserName" class="text-danger"></span>
                </div>
            </div>
    ....
    </form>

控制器:

[HttpPost]
public async Task<IActionResult> EditUser(EditUserViewModel editUserViewModel)
{
    var user = await _userManager.FindByIdAsync(editUserViewModel.Id);

    if (user != null)
    {
        user.UserName = editUserViewModel.UserName;
        user.FirstName = editUserViewModel.FirstName;
        user.LastName = editUserViewModel.LastName;

        var result = await _userManager.UpdateAsync(user);
        if (ModelState.IsValid)
        {

            if (result.Succeeded)
                return Json("Ok");
        }
        else
        {
            return Json(new
            {
                ModalClose = false,
                Data = _renderer.RenderToStringAsync("EditUser", editUserViewModel)
            });

        }

    }

    return RedirectToAction("UserManagement", _userManager.Users);
}

填写结果:

function onSuccess(data, status, xhr) 
{

    $("#" + modid + " .modal-body").empty();
    $("#" + modid + " .modal-body").html(data.data.result);

 }

视图模型:

    public class EditUserViewModel
    {
        public string Id { get; set; }

        [Display(Name = "User Name")]
        [Required(ErrorMessage = "UserName required")]       
        public string UserName { get; set; }

        [Display(Name = "First Name")]
        [Required(ErrorMessage = "FirstName required")]
        public string FirstName { get; set; }
}

1 个答案:

答案 0 :(得分:1)

我已添加到Startup.cs:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), _contenxt.ActionContext?.ModelState ?? new ModelStateDictionary())
 {
  Model = model
 };

似乎有效