其他分享
首页 > 其他分享> > 渲染视图到字符串:ArgumentOutOfRangeException

渲染视图到字符串:ArgumentOutOfRangeException

作者:互联网

我有一个asp.net核心应用程序,并且有一个名为ViewRenderService的服务,该服务将视图转换为字符串,以便我根据发出的请求呈现某些视图.

ViewRenderService:

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.GetView(viewName, 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.GetStringBuilder().ToString();
            }
        }
    }

该行:

await viewResult.View.RenderAsync

抛出

“System.ArgumentOutOfRangeException: Index was out of range. Must be
non-negative and less than the size of the collection.Parameter name:
index”

在某些模型/视图上

视图和模型在以下方面引发异常:

VerifyCodeViewModel:

public class VerifyCodeViewModel
    {
        [Required (ErrorMessage = "Please enter verification code that was sent via email")]
        public string Code { get; set; }
        public string ReturnUrl { get; set; }
    }

Verify.cshtml

@model VerifyCodeViewModel


<div class="row">
    <div class="col s12 m5 l5 push-m3 push-l3 center">
        <div class="center">
            <br />
            <form method="post" asp-action="Verify">
                <div class="card">
                    <div class="card-content">
                        <div class="red-text text-bold" asp-validation-summary="ModelOnly"></div>
                        <div class="row">
                            <div class="col 12 m12 l12">
                                <h4 class="text-bold header caption-uppercase">Verification Token Required</h4>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col s12 m12 l12">
                                <p class="center-align">
                                    An email that contains a token have been sent to you. Please enter token below.
                                </p>
                            </div>
                        </div>
                        <div class="row">
                            <div class="input-field col 12 m12 l12">
                                <i class="mdi-communication-vpn-key prefix"></i>
                                <input type="text" asp-for="Code" placeholder="Enter token here"/>
                                <span asp-validation-for="Code"></span>
                                <span class="text-bold red-text">@ViewBag.Message</span>
                            </div>
                        </div>
                    </div>
                    <div class="card-action">
                        <button type="submit" class="btn btn-danger">Verify</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

@section Scripts {
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

请指导我有关我所缺少的内容,因为它确实适用于某些视图,但不适用于上述视图.

解决方法:

我遇到了同样的问题,并通过检查调用堆栈找到了答案.我这边的问题是:

at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) 
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Microsoft.AspNetCore.Mvc.Routing.UrlHelper.get_Router()
at Microsoft.AspNetCore.Mvc.Routing.UrlHelper.GetVirtualPathData(String routeName, RouteValueDictionary values)
at Microsoft.AspNetCore.Mvc.Routing.UrlHelper.Action(UrlActionContext actionContext)

因此缺少了路由器,并且通过将代码更改为以下内容解决了此问题:

public class ViewRenderService : IViewRenderService
{
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IServiceProvider _serviceProvider;
    private readonly HttpContext _context;

    public ViewRenderService(IRazorViewEngine razorViewEngine,
        ITempDataProvider tempDataProvider,
        IServiceProvider serviceProvider,
        IHttpContextAccessor accessor)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
        _context = accessor.HttpContext;
    }

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

        using (var sw = new StringWriter())
        {
            var viewResult = _razorViewEngine.GetView(viewName, 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()
            );
            viewContext.RouteData = _context.GetRouteData();

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

实际上帮助将上下文从新的ActionContext更改为注入的上下文.通过更改此设置,然后设置RouteData,可以解决此问题.

        viewContext.RouteData = _context.GetRouteData();

标签:razorengine,asp-net-core,asp-net,c,asp-net-mvc
来源: https://codeday.me/bug/20191025/1932531.html