mare
mare

Reputation: 13083

ASP.NET MVC actions with optional params

I have an MVC action on my abstract BaseControlller like this (and this action is common across all inheriting controllers):

    //
    // GET: /controller/RenderForm/{formType}
    [Authorize(Roles = "Administrators")]
    public ActionResult RenderForm(FormType formType, BaseContentObject contentObject)
    {
        string constructPartialViewName = RouteData.Values["controller"] + "-" + formType + "Form";
        return PartialView(constructPartialViewName, contentObject);
    }

with this route:

        routes.MapRoute(
            "ContentObjectsFormRendering",
            RouteType.Regular,
            "{controller}/RenderForm/{formType}",
            new {controller = "", action = "RenderForm", formType = ""}, null
            );

The problem comes in when I make a browser request like:

~/Page/RenderForm/Create

This is a request to render a Create form. This is done from the browser - for instance, typing in the URL. There is no BaseContentObject instance here (please note that this can never be provided thru browser for Create as it is always pulled out of datastore in case of editing) and I think this is what is bothering him.

(The exception is: Cannot create an abstract class.)

But when performing RenderAction like this:

    <%
        Html.RenderAction("RenderForm", ViewData.Model.ContentType.ToString(), new {formType = FormType.Edit, contentObject = ViewData.Model}); %>

it renders the Edit form with details from BaseContentObject instance (provided thru ViewData) just fine.

If I remove the BaseContentObject contentObject parameter from the action then rendering Create works fine but then I cannot provide the content object param in the second case for Edit.

How can I solve this?

Upvotes: 0

Views: 400

Answers (1)

queen3
queen3

Reputation: 15521

Since your RenderForm is common (in base controller) then MVC uses this method's signature to instantiate paramters. This goes like this:

  • action is RenderForm(FormType formType, BaseContentObject contentObject)
  • there's form data like "contentObject.Property" thus MVC needs to instantiate contentObject
  • a type for contentObject is BaseContentObject
  • BaseContentObject cannot be instantiated since it's abstract

Your problem is that you think that if you override RenderForm with different/specific contentObject parameter type then the new parameter type will be used - but from what I see here this is wrong. The base method signature will be used.

Solutions:

  • override DefaultModelBinder and tweak instantiation there; I'm not sure if you can detect real action/parameter type, though;
  • don't use common base RenderForm action; extract required common functionality into protected base method (e.g. DoRenderForm) and call it from real actions.

Upvotes: 1

Related Questions