Fix for #215 - nullref trying to generate link in a partial
The fix here is to do some cleanup we've been planning to do for a while, rather than flowing IUrlHelper and IComponentHelper as part of the ViewContext, they now are just grabbed from the service provider. This simplifies the code for invoking a view, and gets us closer to the desired API surface of ViewContext
This commit is contained in:
parent
749789c486
commit
ab605ef935
|
|
@ -1,4 +1,6 @@
|
||||||
@using MvcSample.Web.Models
|
@using MvcSample.Web.Models
|
||||||
@model User
|
@model User
|
||||||
|
|
||||||
<strong>Hello @Model.Name from Partial</strong>
|
<strong>Hello @Model.Name from Partial</strong>
|
||||||
|
|
||||||
|
<a href="@Url.Action("Edit", "Home")">Edit Something!</a>
|
||||||
|
|
@ -51,16 +51,10 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
var viewContext = new ViewContext(_serviceProvider, actionContext.HttpContext, actionContext.RouteValues)
|
var viewContext = new ViewContext(_serviceProvider, actionContext.HttpContext, actionContext.RouteValues)
|
||||||
{
|
{
|
||||||
Url = urlHelper,
|
|
||||||
ViewData = ViewData,
|
ViewData = ViewData,
|
||||||
Writer = writer,
|
Writer = writer,
|
||||||
};
|
};
|
||||||
|
|
||||||
viewContext.Component = new DefaultViewComponentHelper(
|
|
||||||
_serviceProvider.GetService<IViewComponentSelector>(),
|
|
||||||
_serviceProvider.GetService<IViewComponentInvokerFactory>(),
|
|
||||||
viewContext);
|
|
||||||
|
|
||||||
return viewContext;
|
return viewContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,23 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
|
||||||
private const string HiddenListItem = @"<li style=""display:none""></li>";
|
private const string HiddenListItem = @"<li style=""display:none""></li>";
|
||||||
|
|
||||||
|
private readonly IUrlHelper _urlHelper;
|
||||||
|
private readonly IViewEngine _viewEngine;
|
||||||
|
|
||||||
private ViewContext _viewContext;
|
private ViewContext _viewContext;
|
||||||
private IViewEngine _viewEngine;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HtmlHelper"/> class.
|
/// Initializes a new instance of the <see cref="HtmlHelper"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HtmlHelper([NotNull] IViewEngine viewEngine, [NotNull] IModelMetadataProvider metadataProvider)
|
public HtmlHelper(
|
||||||
|
[NotNull] IViewEngine viewEngine,
|
||||||
|
[NotNull] IModelMetadataProvider metadataProvider,
|
||||||
|
[NotNull] IUrlHelper urlHelper)
|
||||||
{
|
{
|
||||||
_viewEngine = viewEngine;
|
_viewEngine = viewEngine;
|
||||||
MetadataProvider = metadataProvider;
|
MetadataProvider = metadataProvider;
|
||||||
|
_urlHelper = urlHelper;
|
||||||
|
|
||||||
// Underscores are fine characters in id's.
|
// Underscores are fine characters in id's.
|
||||||
IdAttributeDotReplacement = "_";
|
IdAttributeDotReplacement = "_";
|
||||||
|
|
@ -445,8 +452,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
protected virtual MvcForm GenerateForm(string actionName, string controllerName, object routeValues,
|
protected virtual MvcForm GenerateForm(string actionName, string controllerName, object routeValues,
|
||||||
FormMethod method, IDictionary<string, object> htmlAttributes)
|
FormMethod method, IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
var urlHelper = ViewContext.Url;
|
var formAction = _urlHelper.Action(action: actionName, controller: controllerName, values: routeValues);
|
||||||
var formAction = urlHelper.Action(action: actionName, controller: controllerName, values: routeValues);
|
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("form");
|
var tagBuilder = new TagBuilder("form");
|
||||||
tagBuilder.MergeAttributes(htmlAttributes);
|
tagBuilder.MergeAttributes(htmlAttributes);
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HtmlHelper{TModel}"/> class.
|
/// Initializes a new instance of the <see cref="HtmlHelper{TModel}"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HtmlHelper([NotNull] IViewEngine viewEngine, [NotNull] IModelMetadataProvider metadataProvider)
|
public HtmlHelper(
|
||||||
: base(viewEngine, metadataProvider)
|
[NotNull] IViewEngine viewEngine,
|
||||||
|
[NotNull] IModelMetadataProvider metadataProvider,
|
||||||
|
[NotNull] IUrlHelper urlHelper)
|
||||||
|
: base(viewEngine, metadataProvider, urlHelper)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,22 @@ using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
public class DefaultViewComponentHelper : IViewComponentHelper
|
public class DefaultViewComponentHelper : IViewComponentHelper, ICanHasViewContext
|
||||||
{
|
{
|
||||||
private readonly IViewComponentInvokerFactory _invokerFactory;
|
private readonly IViewComponentInvokerFactory _invokerFactory;
|
||||||
private readonly IViewComponentSelector _selector;
|
private readonly IViewComponentSelector _selector;
|
||||||
private readonly ViewContext _viewContext;
|
private ViewContext _viewContext;
|
||||||
|
|
||||||
public DefaultViewComponentHelper(
|
public DefaultViewComponentHelper(
|
||||||
[NotNull] IViewComponentSelector selector,
|
[NotNull] IViewComponentSelector selector,
|
||||||
[NotNull] IViewComponentInvokerFactory invokerFactory,
|
[NotNull] IViewComponentInvokerFactory invokerFactory)
|
||||||
[NotNull] ViewContext viewContext)
|
|
||||||
{
|
{
|
||||||
_selector = selector;
|
_selector = selector;
|
||||||
_invokerFactory = invokerFactory;
|
_invokerFactory = invokerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Contextualize([NotNull] ViewContext viewContext)
|
||||||
|
{
|
||||||
_viewContext = viewContext;
|
_viewContext = viewContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
context.ViewContext.HttpContext,
|
context.ViewContext.HttpContext,
|
||||||
context.ViewContext.ViewEngineContext)
|
context.ViewContext.ViewEngineContext)
|
||||||
{
|
{
|
||||||
Component = context.ViewContext.Component,
|
|
||||||
Url = context.ViewContext.Url,
|
|
||||||
ViewData = _viewData ?? context.ViewContext.ViewData,
|
ViewData = _viewData ?? context.ViewContext.ViewData,
|
||||||
Writer = context.Writer,
|
Writer = context.Writer,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
ClientValidationEnabled = true;
|
ClientValidationEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IViewComponentHelper Component { get; set; }
|
|
||||||
|
|
||||||
public virtual FormContext FormContext
|
public virtual FormContext FormContext
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -52,8 +50,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
public IServiceProvider ServiceProvider { get; private set; }
|
public IServiceProvider ServiceProvider { get; private set; }
|
||||||
|
|
||||||
public IUrlHelper Url { get; set; }
|
|
||||||
|
|
||||||
public bool UnobtrusiveJavaScriptEnabled { get; set; }
|
public bool UnobtrusiveJavaScriptEnabled { get; set; }
|
||||||
|
|
||||||
public bool ClientValidationEnabled { get; set; }
|
public bool ClientValidationEnabled { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -15,21 +15,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
private readonly HashSet<string> _renderedSections = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
private readonly HashSet<string> _renderedSections = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
private bool _renderedBody;
|
private bool _renderedBody;
|
||||||
|
|
||||||
public IViewComponentHelper Component
|
|
||||||
{
|
|
||||||
get { return Context == null ? null : Context.Component; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ViewContext Context { get; set; }
|
public ViewContext Context { get; set; }
|
||||||
|
|
||||||
public string Layout { get; set; }
|
public string Layout { get; set; }
|
||||||
|
|
||||||
protected TextWriter Output { get; set; }
|
protected TextWriter Output { get; set; }
|
||||||
|
|
||||||
public IUrlHelper Url
|
public IUrlHelper Url { get; private set; }
|
||||||
{
|
|
||||||
get { return Context == null ? null : Context.Url; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public dynamic ViewBag
|
public dynamic ViewBag
|
||||||
{
|
{
|
||||||
|
|
@ -50,6 +42,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
SectionWriters = new Dictionary<string, HelperResult>(StringComparer.OrdinalIgnoreCase);
|
SectionWriters = new Dictionary<string, HelperResult>(StringComparer.OrdinalIgnoreCase);
|
||||||
Context = context;
|
Context = context;
|
||||||
|
|
||||||
|
Url = context.ServiceProvider.GetService<IUrlHelper>();
|
||||||
|
|
||||||
var contentBuilder = new StringBuilder(1024);
|
var contentBuilder = new StringBuilder(1024);
|
||||||
using (var bodyWriter = new StringWriter(contentBuilder))
|
using (var bodyWriter = new StringWriter(contentBuilder))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
public ViewDataDictionary<TModel> ViewData { get; private set; }
|
public ViewDataDictionary<TModel> ViewData { get; private set; }
|
||||||
|
|
||||||
|
public IViewComponentHelper Component { get; private set; }
|
||||||
|
|
||||||
public IHtmlHelper<TModel> Html { get; set; }
|
public IHtmlHelper<TModel> Html { get; set; }
|
||||||
|
|
||||||
public override Task RenderAsync([NotNull] ViewContext context)
|
public override Task RenderAsync([NotNull] ViewContext context)
|
||||||
|
|
@ -53,6 +55,14 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
contextable.Contextualize(context);
|
contextable.Contextualize(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component = context.ServiceProvider.GetService<IViewComponentHelper>();
|
||||||
|
|
||||||
|
contextable = Component as ICanHasViewContext;
|
||||||
|
if (contextable != null)
|
||||||
|
{
|
||||||
|
contextable.Contextualize(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
|
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
|
||||||
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>, DefaultViewComponentInvokerProvider>();
|
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>, DefaultViewComponentInvokerProvider>();
|
||||||
yield return describe.Transient<IViewComponentResultHelper, DefaultViewComponentResultHelper>();
|
yield return describe.Transient<IViewComponentResultHelper, DefaultViewComponentResultHelper>();
|
||||||
|
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
|
||||||
|
|
||||||
yield return
|
yield return
|
||||||
describe.Describe(
|
describe.Describe(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue