【问题标题】:web api 2 area routesweb api 2 区域路由
【发布时间】:2015-05-21 10:26:49
【问题描述】:

我正在使用 asp.net mvc 5 和 web api 2。对于 asp.net mvc 5 项目,我一切正常...但是新的我正在尝试添加 web api 2 路由...当我使用区域时.

我有 web api 2 控制器在项目根目录工作:

 //this is working 
   namespace EtracsWeb.Controllers
    {
        public class TestController : ApiController
        {
            //localhost:port/api/test ...this is working
            [HttpGet]
            public HttpResponseMessage Get()
            {

                return new HttpResponseMessage()
                {
                    Content = new StringContent("GET: Test message")
                };
            }

        }
    }

所以我假设我的Global.asax、我的routeconfig.cs 和我的webapiconfig.cs 是正确的......(未显示)......

但现在我正试图让我的 AREAS 中的 web api 2 工作......

我已经阅读了我在网上可以找到的所有内容,这似乎应该 工作:

namespace EtracsWeb.Areas.WorkOrder
{
    public class WorkOrderAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "WorkOrder";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {

            context.Routes.MapHttpRoute(
                    name: "AuditModel_Api",
                    routeTemplate: "WorkOrder/api/AuditModelApi/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

        //default
            context.Routes.MapHttpRoute(
                    name: "WorkOrder_Api",
                    routeTemplate: "WorkOrder/api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

            context.MapRoute(
                 "WorkOrder_default",
                "WorkOrder/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

我的控制器代码是:

namespace EtracsWeb.Areas.WorkOrder.ApiControllers
{
    public class AuditModelApiController : ApiController
    {
        IManufacturerStopOrderModelService auditModelService = new WorkOrder.Services.VWAuditModelService(UserSession.EtracsUserID, UserSession.ProgramID, UserSession.EtracsSessionID, UserSession.ConnectionString);

        [HttpGet]
        [Route("AuditModelApi")]
        public HttpResponseMessage Get()
        {

            return new HttpResponseMessage()
            {
                Content = new StringContent("GET: Test message")
            };
        }

        [Route("AuditModelApi/AuditModels")]
        public IEnumerable<VwAuditModel1> GetAuditModels()
        {
                return auditModelService.GetModels();
        }

        public IHttpActionResult UpdateAuditMode()
        {
            //example of what can be returned ... NotFound, Ok ... look into uses...

            VwAuditModel1 result = new VwAuditModel1();
            return Ok(result);

            return NotFound();
        }
    }
}

我已经尝试了带有和不带有属性命名[Route]的控制器... 而且我也不能去上班……

简单案例

    public HttpResponseMessage Get()

和“真实”案例

  public IEnumerable<VwAuditModel1> GetAuditModels()

返回相同的结果。在浏览器中,使用

http://localhost:64167/WorkOrder/api/AuditModelApi

http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels

我得到以下信息:

<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'.
</Message>
<MessageDetail>
No route providing a controller name was found to match request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'
</MessageDetail>
</Error>

【问题讨论】:

  • 将 webapiconfig.cs 代码添加到您的帖子中。这就是我假设你缺少注册属性路由的地方。

标签: asp.net-mvc-5 asp.net-mvc-routing asp.net-web-api2 asp.net-mvc-areas


【解决方案1】:

首先,你应该用它所属的区域注册路由,这才有意义,所以在你的AreaNameAreaRegistration类中一定要添加using System.Web.Http,这样你就可以得到扩展方法MapHttpRoute,它不是System.Web.Mvc.

上面的顺序有点偏,导致404。添加如下Route:

context.Routes.MapHttpRoute(
            name: "AreaNameWebApi",
            routeTemplate: "api/AreaName/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

如果您想花哨并附加属性 AreaName 中的区域名称(当然您关心良好的编码实践;)):

context.Routes.MapHttpRoute(
            name: "AreaNameWebApi",
            routeTemplate: string.Concat("api/", AreaName, "/{controller}/{id}"),
            defaults: new { id = RouteParameter.Optional }
        );

这将纠正 404 问题。默认情况下,在 Web API 模块中,它首先扫描“api”以确定在哪里查找控制器(否则会混淆,这不是魔术),因此在动态附加区域名称和控制器时需要首先使用 api。当然,您可以通过硬编码路由来更改此顺序,但我不建议您这样做,因为您需要在路由配置中提供每条路由和每个控制器,或者使用 RouteAttribute

另外,首先使用“api”,它将为您和您的用户创建一个漂亮的标准 URL,而不是到处都有 API。以下是一些示例:

http://site/api/members/myAccount/update
http://site/api/members/myAccount/get/12345
http://site/api/members/contacts/getByOwnerId/12345

希望这会有所帮助!

泽夫

【讨论】:

  • 终于!网上有人回答了这个问题。我永远不会想到这一点。现在我明白了。从ApiController 派生Web.Api 控制器时,您需要在AreaRegistration 中使用MapHttpRoute()(对于常规MVC Controller,您将使用MapRoute())。添加using System.Web.Http 是关键。然后我在App_Start/WebApiConfig.cs 文件中注释掉了自动生成的MapHttpRoute() 代码以避免任何混淆。此外,我喜欢将“api/”前缀标准化以首先出现在 Url 中的想法 - 即使在区域内也是如此。非常感谢!
【解决方案2】:

您需要从GlobalConfiguration 对象中获取HttpConfiguration 实例,并从AreaRegistration.csRegisterArea() 方法内部调用MapHttpAttributeRoutes() 方法。

    public override void RegisterArea(AreaRegistrationContext context) 
    {
        GlobalConfiguration.Configuration.MapHttpAttributeRoutes();

        //... omitted code  
    }

最后你必须在WebApiConfig 中删除config.MapHttpAttributes() 方法,否则你会得到重复的异常。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.EnableCors();

        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


        // Web API routes
        //config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

【讨论】:

  • 从 Web Api v2 开始看起来像 should instead be GlobalConfiguration.Configure(x =&gt; x.MapHttpAttributeRoutes())
【解决方案3】:

该特定 API 调用的问题是您没有指定要在路由中使用的控制器。

        context.Routes.MapHttpRoute(
                name: "AuditModel_Api",
                routeTemplate: "WorkOrder/api/AuditModelApi/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

应该是

        context.Routes.MapHttpRoute(
                name: "AuditModel_Api",
                routeTemplate: "WorkOrder/api/AuditModelApi/{id}",
                defaults: new { controller = "AuditModelApi", id = RouteParameter.Optional }
            );

URL 中的常量段用于指定要匹配的 URL,但您仍然必须告诉它路由值是什么,以便它到达控制器和操作。除非您将其设为{controller} 段,否则它无法知道将哪个段用作控制器名称。

【讨论】:

  • 这确实有效...谢谢...但这会将区域绑定到一个控制器..如果有多个控制器,我们该怎么办?
  • 在这种情况下,您可以使用控制器占位符指定 routeTemplate 参数:WorkOrder/api/{controller}/{id)
  • 我是注册的原始代码我已经尝试过这个的变体......没有指定控制器并使用你给的路由......它给出了一个错误,它找不到资源(再次查看原始消息)...我认为这是正确的... mapphttproute 语句有什么问题吗?
  • 我不能说。但请注意,路由是特定于订单的。如果您在要匹配的路由之前有另一个匹配该 URL 的路由,它将尝试路由到错误的控制器。发布您的整个路由配置,包括您在 Application_Start 中的内容,也许可以发现问题。
猜你喜欢
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2011-03-17
  • 2016-12-06
  • 1970-01-01
  • 2012-04-19
相关资源
最近更新 更多