Sniff, page parameter in my controller is null

PLACE FOR BLOG

Sniff, page parameter in my controller is null

Sniff, page parameter in my controller is null

marija

FACT: VS extensions and copy paste rock when creating new EPiServer items.

BUT: We have written the code like 100 times, so why bother clicking when we can type. <= This kind of thinking might just be wrong.

I've had a colleague banging his head over an exception he is getting when rendering a block. Seemingly, everything was correct and should be working.

However, he did exactly what was explained in the introSniff, page parameter in my controller is null: typed in the controller code without using VS extensions and it was an unintentional typo that cost him some hours:

    public override ActionResult Index(PageListBlock currentPage)

Looks good? The exception was:

    EPiServer.Core.TypeMismatchException: The routed data is of type 'PROJECT.Models.Pages.StartPage' and the binding context 'currentPage' is null, cannot bind any value to type 'PROJECT.Models.Blocks.PageListBlock'.

It's even worse when you simply see a null in the debugger for the currentPage parameter.

The issue is that you really really need to name your parameter properly. For a block controller - currentBlock and for a page - currentPage.

I've conducted a short experiment, so you get the following results when you play around and some results are a bit funny, but the general conclusion is simple. If you are troubleshooting on why your controller parameter is null or your block controller acts crazy, consider the naming of the parameter!

Results for the page controller:

  • StartPage currentPage => default, works like charm
  • StartPage whatever => whatever is null
  • StartPage currentBlock => is *amazingly* correct
  • StartPage currentContent => correct as well
  • StartPage startPage => startPage is null

Results for block controller:

  • PageListBlock currentBlock => default, works like charm
  • PageListBlock currentPage => ERROR Additional information: The routed data is of type 'MarijasPlayground.Models.Pages.StartPage' and the binding context 'currentPage' is null, cannot bind any value to type
  • PageListBlock currentContent => correct as well
  • PageListBlock pageListBlock => null
  • PageListBlock whatever => null

Similar goes for the PartialContentController:

  • IContentData currentContent => correct, works well
  • IContentData currentPage => incorrect, gives a reference to the current page where the content is presented instead of content itself
  • IContentData currentBlock => works well, for the page as well surprisingly
  • IContentData whatever => null

Why is this so?

If we take a peek in ContentDataModelBinder and ContentDataValueProvider (namespace EPiServer.Web.Mvc), we'll see the following:

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
      ...
      ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
      if (valueProviderResult == null)
        return (object) null;
      ...
    }

    public ValueProviderResult GetValue(string key)
    {
      if (this.ContainsPrefix(key)) { ... }
      return (ValueProviderResult) null;
    }

    public bool ContainsPrefix(string prefix)
    {
      if (string.IsNullOrEmpty(prefix)) return false;
      if (!this.IsPageKey(prefix) && !this.IsContentKey(prefix))
        return this.IsBlockKey(prefix);
      return true;
    }

    private bool IsPageKey(string key)
    {
      return string.Equals(key, this.CurrentPageKey, StringComparison.OrdinalIgnoreCase);
    }
    
public ContentDataValueProvider(System.Web.Routing.RequestContext requestContext, ViewContentRetriever contentRetriever)
    {
      ...
      this.CurrentPageKey = "currentPage";
      this.CurrentBlockKey = "currentBlock";
      this.CurrentContentKey = "currentContent";
    }

Moral

You might as well skip the explanation and just remember to use VS extensions :)

LEAVE A COMMENT