MVC Action with Optional Parameters — which is bet

2019-02-04 03:06发布

问题:

Are there any pros/cons of using the following two alternatives in your action signature:

public ActionResult Action(int? x) // get MVC to bind null when no parameter is provided
{
    if(x.HasValue)
    {
        // do something
    }
}

OR

public ActionResult Action(int? x = null) // C# optional parameter (virtual overload)
{
    if(x.HasValue)
    {
        // do something
    }
}

回答1:

I have never seen the second action signature in practice and can't see any usefulness of it.

The first one usually covers all the scenarios:

  • If no parameter is sent (GET /somecontroller/action), the value of the x argument will be null inside the action
  • If a x parameter is sent, but it is not a valid integer (GET /somecontroller/action?x=abc), the value of the x argument will be null inside the action and the modelstate will be invalid
  • If a x parameter is sent and the value represents a valid integer (GET /somecontroller/action?x=123), then x will be assigned to it.

In my examples I have used GET requests with query string parameters but obviously the same applies with other HTTP verbs and if x was a route parameter.



回答2:

You only need to specify the optional parameter value if it is going to be anything else other than null.

MVC3 will automatically set null as the value of your parameter if nothing is specified in the overload, or in the call to the Action.

However, its worth noting that if there are any non-optional parameters after this parameter in the signature, then null would have to be specified in the call.

Therefore its best to put all optional params at the end of the signature.



回答3:

Best Asp.net MVC solution - use action method selector

Why not simplify controller action methods by removing unnecessary code branch and have this kind of code as seen here:

public ActionResult Index()
{
    // do something when there's no id
}

[RequiresRouteValues("id")]
public ActionResult Index(int id)
{
    // do something when id is present
}

This is of course possible, as long as you provide the very simple code for RequiresRouteValuesAttribute action method selector. You can find code in this blog post that does exactly this.

By my opinion this is the best possible solution to this problem, because:

  1. It simplifies code by removing unnecessary branch
  2. Makes code easier to maintain (due to lower complexity)
  3. Extends Asp.net MVC framework as it can and should
  4. Keeps parameter types as they should be without the need to make them nullable
  5. etc.

Anyway. All the details about this technique is explained in great detail in linked post.