使用不同控制器但动作名称相同的路由无法生成所需的网址 [英] Routes with different controllers but same action name fails to produce wanted urls

查看:56
本文介绍了使用不同控制器但动作名称相同的路由无法生成所需的网址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的MVC Web应用程序设置一个API,该API会有很多路由,但每个路由都有很多相同的部分.基本上每个区域都有CRUD.我还将其设置为可版本控制.我已经设置了两个控制器,每个控制器都有一个简单的操作即可开始并立即获得冲突.我得到的错误是

I am trying to set up a API for my MVC web app that will have a lot of routes but much of the same part for each one. Basically a CRUD for each area. I am also setting it up to be version-able. I have set up two controllers each with a simple action to get started and receive a conflict right off the bat. The error I get is

我在这些网址之后

MVC将让您拥有

因此,我正在寻找一种不必要的命名方式,例如 contacts_delete locations_delete 这样的生成URL的

So I am looking for a away around needlessly naming things like contacts_delete and locations_delete producing URLs like

  • https://foo.bar/aim/v1/contacts/contacts_delete/11111
  • https://foo.bar/aim/v1/locations/locations_delete/11111
  • and so on

(这是注释中提供的根本问题的观察,并且这样的anwsers之下的路由名称必须是唯一的.您不能有两个名为delete的不同路由.请使用deleteLocation和deleteContact代替).)

我也可以只做 https://foo.bar/aim/v1/contacts_delete/11111 ,但这对我来说似乎是毫无意义的.如果MVC能够做到这一点,我必须相信有一种方法可以做到这一点.

I may as well just do https://foo.bar/aim/v1/contacts_delete/11111 but that seems so senseless to me. If the MVC can do it, i have to believe that there is a way to make this happen.

我得到的错误是:

名称为"delete"的属性路由必须具有相同的模板:

Attribute routes with the same name 'delete' must have the same template:

操作:'rest.fais.foo.edu.Controllers.aimContactsController.delete(rest.fais.foo.edu)'-模板:'aim/v1/contacts/delete/{id}'

Action: 'rest.fais.foo.edu.Controllers.aimContactsController.delete (rest.fais.foo.edu)' - Template: 'aim/v1/contacts/delete/{id}'

操作:"rest.fais.foo.edu.Controllers.aimLocationsController.delete(rest.fais.foo.edu)"-模板:"aim/v1/locations/delete/{id}"

Action: 'rest.fais.foo.edu.Controllers.aimLocationsController.delete (rest.fais.foo.edu)' - Template: 'aim/v1/locations/delete/{id}'

对于我已设置的控制器

[EnableCors("SubDomains")]
[ResponseCache(NoStore = true, Duration = 0)]
[Produces("application/json")]
[Route("aim/v1/contacts/[action]")]
[ProducesResponseType(typeof(errorJson), 500)]
public class aimContactsController : Controller
{
    private readonly IHostingEnvironment _appEnvironment;
    private readonly AimDbContext _aim_context;
    private readonly UserManager<ApplicationUser> _userManager;

    public aimContactsController(IHostingEnvironment appEnvironment,
        AimDbContext aim_context,
        UserManager<ApplicationUser> userManager)
    {
        _appEnvironment = appEnvironment;
        _userManager = userManager;
        _aim_context = aim_context;
    }



    [HttpPost("{id}", Name = "delete")]
    public IActionResult delete(string id)
    {

        return Json(new
        {
            results = "deleted"
        });
    }

}


[EnableCors("SubDomains")]
[ResponseCache(NoStore = true, Duration = 0)]
[Produces("application/json")]
[Route("aim/v1/locations/[action]")]
[ProducesResponseType(typeof(errorJson), 500)]
public class aimLocationsController : Controller
{
    private readonly IHostingEnvironment _appEnvironment;
    private readonly AimDbContext _aim_context;
    private readonly UserManager<ApplicationUser> _userManager;

    public aimLocationsController(IHostingEnvironment appEnvironment,
        AimDbContext aim_context,
        UserManager<ApplicationUser> userManager)
    {
        _appEnvironment = appEnvironment;
        _userManager = userManager;
        _aim_context = aim_context;
    }



    [HttpPost("{id}", Name = "delete")]
    public IActionResult delete(string id)
    {

        return Json(new
        {
            results = "deleted"
        });
    }

}

对于 Startup.cs ,我有

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        //RolesData.SeedRoles(app.ApplicationServices).Wait();

        app.UseApplicationInsightsRequestTelemetry();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            //app.UseExceptionHandler("/Home/Error");
        }

        app.UseIdentity();
        app.UseDefaultFiles();
        app.UseStaticFiles();

        //app.UseResponseCompression();

        // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
        app.UseSession();

        // custom Authentication Middleware
        app.UseWhen(x => (x.Request.Path.StartsWithSegments("/aim_write", StringComparison.OrdinalIgnoreCase) || x.Request.Path.StartsWithSegments("/rms", StringComparison.OrdinalIgnoreCase)),
        builder =>
        {
            builder.UseMiddleware<AuthenticationMiddleware>();
        });

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = "docs";
            //c.SwaggerEndpoint("/docs/v1/wsu_restful.json", "v1.0.0");swagger
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1.0.0");
        });


        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "javascript",
                template: "javascript/{action}.js",
                defaults: new { controller = "mainline" });
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute(
                name: "AIMApi",
                template: "aim/v1/{action}/{id?}",
                defaults: new { controller = "aim" });
            routes.MapRoute(
                name: "AIMContactsApi",
                template: "aim/v1/contacts/{action}/{id?}",
                defaults: new { controller = "aimContactsController" }
            );
            routes.MapRoute(
                name: "AIMLocationsApi",
                template: "aim/v1/locations/{action}/{id?}",
                defaults: new { controller = "aimLocationsController" }
            );
            routes.MapRoute(
                name: "RMSApi",
                template: "{controller=rms}/v1/{action}/{id?}");
        });
    }
}

我似乎无法找到答案解决该问题的方法.我想解决眼前的问题,但任何建议都值得欢迎.

What I can't seem to google out the answer how to work around this. I want to fix the immediate issue, but any suggests are welcomed.

推荐答案

两个路由都具有相同的名称,这在ASP.NET Core MVC中不起作用.

Both your routes are named the same, this cannot work in ASP.NET Core MVC.

我不是在谈论方法命名,而是在谈论路由命名.您在 HttpPost 属性中使用相同的标识符 Name ="delete" 调用了两条路由.MVC中的路由名称唯一地标识了路由模板.

I'm not talking about the methods naming, but about routes naming. You called both your routes with the same identifier Name = "delete" inside the HttpPost attribute. Route names in MVC uniquely identifies a route template.

据我所知,您实际上不需要标识您的路由,而只是要区分不同的URI.因此,您可以在操作方法上自由删除 HttpPost 属性的 Name 属性.这足以使ASP.NET Core路由器匹配您的操作方法.

From what I can see you do not really need to identify your routes, but only to distinguish different URIs. For this reason you may freely remove the Name property of HttpPost attribute on your action methods. This should be enough for ASP.NET Core router to match your action methods.

如果您只使用属性路由来还原内容,则最好将控制器更改为以下内容:

If you, instead, what to revert using only attribute routing you better change your controller to the following:

// other code omitted for clarity
[Route("aim/v1/contacts/")]
public class aimContactsController : Controller
{
    [HttpPost("delete/{id}")]
    public IActionResult delete(string id)
    {
        // omitted ...
    }
}

这篇关于使用不同控制器但动作名称相同的路由无法生成所需的网址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆