Why Does My EditorTemplate Get Executed Even When Property Is Null?
-
23-02-2021 - |
Question
I've got a model like this:
public class ParentViewModel
{
public class ChildViewModel { get; set; }
// other properties
}
Then in the view for ParentViewModel
, i do this:
@Html.EditorFor(model => model.ChildViewModel)
And it executes my custom editor template, even when Model.ChildViewModel
is null
. Why? I thought MVC was smart enough to only render the view/template when it has a value. (e.g the default template for null
is to not render anything).
Because at the moment, i would have to wrap the HTML in my custom editor template with:
@if (Model != null)
Which seems very silly.
Is this a known problem?
I'm on ASP.NET MVC 3, Razor.
La solution
Rather than testing for null before your partial or inside it you can use a new extension method. This also gives you more options for how to deal with a null model. Here's the extensions I use, it will test for null and either return an empty string or a different partial on a null result. This can be particularly helpful on things like pagers where the page is out of range as you can have a separate partial with your "no results" information.
namespace System.Web.Mvc.Html
{
public static class nullpartials
{
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, object Model)
{
if (Model == null)
return MvcHtmlString.Empty;
else
return helper.Partial(Partial, Model);
}
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
{
if (Model == null)
return helper.Partial(NullPartial);
else
return helper.Partial(Partial, Model);
}
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
return MvcHtmlString.Empty;
else
return helper.Partial(Partial, Model, viewdata);
}
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
return helper.Partial(NullPartial, viewdata);
else
return helper.Partial(Partial, Model, viewdata);
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, object Model)
{
if (Model == null)
{
return;
}
else
{
helper.RenderPartial(Partial, Model);
return;
}
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
{
if (Model == null)
{
helper.RenderPartial(NullPartial);
return;
}
else
{
helper.RenderPartial(Partial, Model);
return;
}
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
{
return;
}
else
{
helper.RenderPartial(Partial, Model, viewdata);
return;
}
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
{
helper.RenderPartial(NullPartial, viewdata);
return;
}
else
{
helper.RenderPartial(Partial, Model, viewdata);
return;
}
}
}
}
Edit
Sorry I misready the question being about EditorTemplates. However I see no reason that the same approach can't work for EditorFor, you just have a few more method signatures to replicate.
Autres conseils
I don't think MVC is that smart. It expects if you call a render method (displayFor, EditFor, Partial) and send it a model, then that model will have a value (else NullReferenceException). Your choices as far as I know are:
- Either have 2 different views (perhaps 2 different view models?)
- Do you model != null check
- Use a renderAction method passing a parameter from your primary model that lets that action know if you should return a view/partial view or return nothing.