ASP.Net MVC RouteAttribute Error with Route Parameter

﹥>﹥吖頭↗ 提交于 2021-01-28 07:44:23

问题


I'm getting a lot of different errors while trying to add Route mapping to a certain action!

I'm trying to get this route for GET /Admin/Users/User/1 and POST /Admin/Users/User

But sadly there is already a User property in Controller! So i cannot use public ActionResult User(long id) because i need to hide the user property (that i need to keep because it's the IPrincipal of the Controller and i still get the same error).

Defining route this way :

// First in RouteConfig
routes.MapMvcAttributeRoutes();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

// Then i'm registering my Areas.

this controller is in Admin Areas. UsersController : Controller

[HttpGet]
[Route(Name = "User/{id:long}")]
public ActionResult GetUser(long id)
{
    var model = new UserViewModel
    {
        User = _usersService.GetUser(id),
        Roles = _rolesService.GetRoleDropdown()
    };

    return View("User");
}

[HttpPost]
[Route(Name = "User")]
public ActionResult GetUser(UserViewModel model)
{
    if (ModelState.IsValid)
    {
        _usersService.UpdateUserRoles(model.User);
        return RedirectToAction("Index");
    }

    return View("User", model);
}

Here is the error i'm getting :

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method 'System.Web.Mvc.ActionResult User(Int64)' in 'MyProjectName.Web.Areas.Admin.Controllers.UsersController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters

I'm not sure to really understand what's wrong!

I checked this page that explain the attributes and i see nothing wrong https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

EDIT 1

It still doesn't work, i changed my registration to

routes.MapMvcAttributeRoutes();

AreaRegistration.RegisterAllAreas();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Here is my full controller code because now it doesn't work for my Index action that was not in the initial code.

[RouteArea("Admin")]
[RoutePrefix("Users")]
public class UsersController : Controller
{
    private readonly IUsersService _usersService;
    private readonly IRolesService _rolesService;

    public UsersController(
        IUsersService usersService,
        IRolesService rolesService)
    {
        _usersService = usersService;
        _rolesService = rolesService;
    }

    [HttpGet]
    [Route(Name = "Index")]
    public ActionResult Index()
    {
        var model = new UsersViewModel
        {
            Users = _usersService.GetUsers()
        };

        return View(model);
    }

    [HttpGet]
    [Route(Name = "User/{id:long}")]
    public new ActionResult User(long id)
    {
        var model = new UserViewModel
        {
            User = _usersService.GetUser(id),
            Roles = _rolesService.GetRoleDropdown()
        };

        return View("User");
    }

    [HttpPost]
    [Route(Name = "User")]
    public new ActionResult User(UserViewModel model)
    {
        if (ModelState.IsValid)
        {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }

        return View("User", model);
    }
}

Now, i'm getting while trying to go to my index action:

The current request is ambiguous between the following action methods: System.Web.Mvc.ActionResult Index() on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController System.Web.Mvc.ActionResult User(Int64) on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController System.Web.Mvc.ActionResult User(EspaceBiere.Web.Areas.Admin.ViewModels.Users.UserViewModel) on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController

and this while trying to go to User Action

A public action method 'User' was not found on controller 'EspaceBiere.Web.Areas.Admin.Controllers.UsersController'.

And my link to the index action was :

tried with /Admin/Users for my Index Action

tried with /Admin/Users/User/1 for User Action

EDIT 2

Ok, my index is now working perfectly, but my user action still is not working! I've removed all the Name properties of the RouteAttribute to keep them in the constructor (as template) -> [Route("User/{id:long}")]

Sorry, if i didn't see them on first read!

Here is the link to the action

                    <a href="@Url.Action("User", "Users", new { Area = "Admin", id = user.UserId })" class="btn btn-warning">
                    <i class="fa fa-pencil"></i>
                </a>

Here is the error

No matching action was found on controller 'EspaceBiere.Web.Areas.Admin.Controllers.UsersController'. This can happen when a controller uses RouteAttribute for routing, but no action on that controller matches the request.

It does work if i write in the URL /Admin/Users/User/1 So how should i write my Url.Action ?


回答1:


You haven't completely understood the concept of using attribute routing if that was your intention. Here is an example of how to configure the routes you wanted.

[RouteArea("Admin")]
[RoutePrefix("Users")]
public class UsersController : Controller {
    private readonly IUsersService _usersService;
    private readonly IRolesService _rolesService;

    public UsersController(
        IUsersService usersService,
        IRolesService rolesService) {
        _usersService = usersService;
        _rolesService = rolesService;
    }

    //GET Admin/Users
    //GET Admin/Users/Index
    [HttpGet]
    [Route("")]
    [Route("Index")]
    public ActionResult Index() {
        var model = new UsersViewModel {
            Users = _usersService.GetUsers()
        };

        return View(model);
    }

    //GET Admin/Users/User/1
    [HttpGet]
    [Route("User/{id:long}", Name = "GetUser")]
    public ActionResult GetUser(long id) {
        var model = new UserViewModel {
            User = _usersService.GetUser(id),
            Roles = _rolesService.GetRoleDropdown()
        };

        return View("User");
    }

    //POST Admin/Users/User
    [HttpPost]
    [Route("User")]
    public ActionResult PostUser(UserViewModel model) {
        if (ModelState.IsValid) {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }

        return View("User", model);
    }
}

If you are using both Areas with route attributes, and areas with convention based routes (set by an AreaRegistration class), then you need to make sure that area registration happen after MVC attribute routes are configured, however before the default convention-based route is set. The reason is that route registration should be ordered from the most specific (attributes) through more general (area registration) to the mist generic (the default route) to avoid generic routes from “hiding” more specific routes by matching incoming requests too early in the pipeline.

// First in RouteConfig
routes.MapMvcAttributeRoutes();

// Then register Areas.
AreaRegistration.RegisterAllAreas();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Route Names

You can specify a name for a route, in order to easily allow URI generation for it. For example, for the following route:

[Route("User/{id:long}", Name = "GetUser")]
public ActionResult GetUser(long id)

you could generate a link using Url.RouteUrl:

<a href="@Url.RouteUrl("GetUser", new { Area = "Admin", id = user.UserId })" class="btn btn-warning">
    <i class="fa fa-pencil"></i>
</a>



回答2:


Nice,

    [HttpPost]
    [Route("User")]
    public ActionResult PostUser(UserViewModel model) {
        if (ModelState.IsValid) {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }enter code here

        return View("User", model);
    }


来源:https://stackoverflow.com/questions/39176031/asp-net-mvc-routeattribute-error-with-route-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!