开发者

asp.net mvc - null parameter exception - could be routing problem?

开发者 https://www.devze.com 2023-03-20 20:52 出处:网络
I\'m kind of new to MVC. I have a controller called PostItemsController in an area called CaseManagers with an action method called GetByUmi(int caseNumber):

I'm kind of new to MVC. I have a controller called PostItemsController in an area called CaseManagers with an action method called GetByUmi(int caseNumber):

[HttpGet]
    public ViewResult ViewByUmi(int umi)
    {
      //implementation omitted
    }

The routing configuration looks like this (not my work):

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
      //ignore route for ico files
      routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?../Images/MauriceFavicon.ico(/.*)?" });
      routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*开发者_运维知识库/)?Images/MauriceFavicon.ico(/.*)?" });
      routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?Content/Images/MauriceFavicon.ico(/.*)?" });
      routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?/favicon.ico(/.*)?" });

      //ignore javascript files routing
      routes.IgnoreRoute("{file}.js");

      //ignore routing for files ending .doc
      routes.IgnoreRoute("{resource}.doc");

      routes.MapRoute(
          "CaseManagers", // Route name         
          "CaseManagers/PostItems/ViewByUmi/{id}", // URL with parameters         
          new { controller = "PostItems" } // Parameter defaults         
);

      //InvoicesLookUp route
      routes.MapRoute(
         "InvoicesLookUpShortDefault", // Route name
         "InvoicesLookUp/{action}/{id}", // URL with parameters
         new { controller = "InvoicesLookUp", action = "Index", area = "Home", id = UrlParameter.Optional } // Parameter defaults
         ,
      null,
      new[] { "MooseMvc.Areas.Accounts.Controllers" } // Parameter defaults
      ).DataTokens.Add("area", "Accounts");


      //Invoices route
      routes.MapRoute(
         "InvoicesShortDefault", // Route name
         "Invoices/{action}/{id}", // URL with parameters
         new { controller = "Invoices", action = "Index", area = "Accounts", id = UrlParameter.Optional } // Parameter defaults
         ,
      null,
      new[] { "MooseMvc.Areas.Accounts.Controllers" } // Parameter defaults
  ).DataTokens.Add("area", "Accounts");




      //administrating route
      routes.MapRoute(
         "AdministratorShortDefault", // Route name
         "Administrator/{action}/{id}", // URL with parameters
         new { controller = "Administrator", action = "Index", area = "Administrator", id = UrlParameter.Optional } // Parameter defaults
     );

      routes.MapRoute(
          "Default", // Route name
          "{controller}/{action}/{id}", // URL with parameters
          new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
      );

      //add root route route
      routes.MapRoute(
      "Root",
      "",
      new { controller = "Home", action = "Index", id = "" }
    );

When I try to call this method with the URL http://localhost:[portnumber]/CaseManagers/PostItems/ViewByUmi/1234 I get the following exception:

The parameters dictionary contains a null entry for parameter 'umi' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ViewResult ViewByUmi(Int32)' in 'MooseMvc.Areas.CaseManagers.Controllers.PostItemsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

I don't intend the ID parameter to be optional and I don't understand why MVC can't find the ID.

Can anyone tell me what I need to do?

EDIT:

Phil Haack's route tester is telling me that the following route is being mapped:

routes.MapRoute(
          "CaseManagers", // Route name         
          "CaseManagers/PostItems/ViewByUmi/{id}", // URL with parameters         
          new { controller = "PostItems" } // Parameter defaults         
);

But it is being mapped AFTER another route CaseManagers/{controller}/{action}/{id}. But this route isn't anywhere in the Global.asax file (take a look, it's reproduced in full above).

Any idea what's going on?


Method parameters in ASP.NET MVC match up 1-1 with route parameters. Since you have no routes that take in a route value named umi, no route will catch what you're trying to do.

You have one of two choices:

  1. If you want the default route to handle that action, then change:

public ViewResult ViewByUmi(int umi) { //implementation omitted }

to:

public ViewResult ViewByUmi(int id)
{ 
    //implementation omitted
}

However, if you want to keep umi(because it has contextual meaning that makes that code easier to follow), then you want to add a route to explicitly deal with it:

//UMI route
  routes.MapRoute(
  "umi",
  "/case/postitems/view/{umi}",
  new { area = "CaseManager", controller = "PostItems", action = "ViewByUmi", umi = "" }
);


Turns out that Global.asax isn't the only place that routing happens. Each of the areas in this application has its AreaRegistration class. I added a new route to the top of this class to produce the following:

public class CaseManagersAreaRegistration : AreaRegistration
  {
    public override string AreaName
    {
      get
      {
        return "CaseManagers";
      }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
      context.MapRoute(
          "PostItems", // Route name         
          "CaseManagers/PostItems/ViewByUmi/{umi}", // URL with parameters         
          new { area = "CaseManagers", controller = "PostItems", action = "GetByUmi", umi = "{umi}" } // Parameter defaults         
);
      context.MapRoute(
          "CaseManagers_default",
          "CaseManagers/{controller}/{action}/{id}",
          new { action = "Index", id = UrlParameter.Optional }
      );
    }
  }

The routing debugger now tells me this is getting matched first. Now I just need to work out why I've got an error telling the the resource cannot be found...


You don't have a route for CaseManagers/PostItems/ViewByUmi/1234 and it would appear that it is taking ViewByUmi and try to convert it to an System.Int32 because it is falling into the Default route. If you create a Route for your CaseManagers you should no longer have this problem.

Use Phil Haacks' Route Debugger to help you out :o)

routes.MapRoute(         
          "CaseManagers", // Route name         
          "CaseManagers/PostItems/ViewByUmi/{id}", // URL with parameters         
          new { controller = "PostItems" } // Parameter defaults         
);
0

精彩评论

暂无评论...
验证码 换一张
取 消