Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 路由属性名称属性_C#_Asp.net_.net_Routing_Asp.net Web Api2 - Fatal编程技术网

C# 路由属性名称属性

C# 路由属性名称属性,c#,asp.net,.net,routing,asp.net-web-api2,C#,Asp.net,.net,Routing,Asp.net Web Api2,我有ProductsController和OwnersController: public class ProductsController : ApiController { //constructor is here // GET /api/products public IHttpActionResult GetProducts() { return Ok(new ApiResponse()); } // GET /ap

我有ProductsController和OwnersController:

public class ProductsController : ApiController
{

    //constructor is here

    // GET /api/products
    public IHttpActionResult GetProducts()
    {
        return Ok(new ApiResponse());
    }

    // GET /api/products/{productCode}
    [HttpGet, Route("api/products/{productCode}")]
    public IHttpActionResult GetProductByCode(string productCode)
    {
         return Ok(new ApiResponse());
    }

    // POST /api/products
    public IHttpActionResult PostProduct(Product product /*my class*/)
    {
        return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
    }
}
它工作得很好。 但是现在我创建了第二个控制器,并且做了同样的事情,但是我在尝试POST方法时遇到了错误。另一种方法很有效

让我们先看一下代码:

public class OwnersController : ApiController
{
    // constructor

    // GET /api/owners/{label}
    // GET /api/owners/{label}?skip=1&take=4
    [Route("api/owners/{label}")]
    public IHttpActionResult GetOwnersExamples(string label, int skip=0, int take=10)
    {
        return Ok(new ApiResponse());
    }
    // POST /api/owners/{productCode}
    //[HttpPost]
    [Route("api/owners/{productCode}"/*, Name = "CreateOwner"*/)]
    public IHttpActionResult PostOwner(string productCode, Owner owner)
    {
        return CreatedAtRoute("DefaultApi", new { id = Owner.Id }, owner);
    }  
}
错误消息:

UrlHelper.Link不能返回null


我的路线图

config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
据我所知,
CreateAtRoute
方法必须获得另一个
RouteName
的问题。如您所见,我可以通过添加Route Name参数(现在已发表评论)并将
的“DefaultApi”
替换为
的“CreateOwner”
来解决这个问题,但它看起来像是一个黑客。我相信还有另一种方法可以避免
Name属性

另外,看起来我的Web API只能看到第一个控制器(ProductsController)-如果我删除显式路由
[Route(“…”)
,任何其他方法都不起作用

据我所知,CreateAtRoute方法必须获得另一个 罗泰娜。如您所见,我可以通过添加路由名称来解决此问题 参数(现在已注释)并将“DefaultApi”替换为“CreateOwner” 但它看起来像一个黑客。我相信还有另一种方法 避免使用名称属性

你的理解几乎是正确的。但是,您不应该为当前路由指定名称,而应该为指向已创建资源的路由指定名称
CreatedAtRoute
填充响应头,该响应头应包含新创建资源的可获取URI

以下是一个工作示例:

[HttpGet]
[Route("api/owners/{id}", Name = "GetOwnerById")]
public IHttpActionResult GetOwner(int id)
{
    //  Obtain the owner by id here
    return Ok(new ApiResponse());
}

[HttpPost]
[Route("api/owners/{productCode}"/*, Name = "CreateOwner"*/)]
public IHttpActionResult PostOwner(string productCode, Owner owner)
{
    return CreatedAtRoute("GetOwnerById", new { id = owner.Id }, owner);
}
(注意:要使此示例正常工作,应注释
GetOwnersExamples
action,否则多个操作将与get请求匹配。)

你说它看起来像黑客,但事实并非如此
CreatedAtRoute
将路由名称作为参数,您应该提供它。否则,如何选择正确的操作并生成
位置
标题

据我所知,CreateAtRoute方法必须获得另一个 罗泰娜。如您所见,我可以通过添加路由名称来解决此问题 参数(现在已注释)并将“DefaultApi”替换为“CreateOwner” 但它看起来像一个黑客。我相信还有另一种方法 避免使用名称属性

你的理解几乎是正确的。但是,您不应该为当前路由指定名称,而应该为指向已创建资源的路由指定名称
CreatedAtRoute
填充响应头,该响应头应包含新创建资源的可获取URI

以下是一个工作示例:

[HttpGet]
[Route("api/owners/{id}", Name = "GetOwnerById")]
public IHttpActionResult GetOwner(int id)
{
    //  Obtain the owner by id here
    return Ok(new ApiResponse());
}

[HttpPost]
[Route("api/owners/{productCode}"/*, Name = "CreateOwner"*/)]
public IHttpActionResult PostOwner(string productCode, Owner owner)
{
    return CreatedAtRoute("GetOwnerById", new { id = owner.Id }, owner);
}
(注意:要使此示例正常工作,应注释
GetOwnersExamples
action,否则多个操作将与get请求匹配。)


你说它看起来像黑客,但事实并非如此
CreatedAtRoute
将路由名称作为参数,您应该提供它。否则,如何选择正确的操作并构建
位置
标题?

我使用以下步骤解决问题:

  • 删除控制器的所有
    [RoutePrefix]
    ——默认情况下让它们工作——它非常适合简单的请求
  • 重要提示:检查所有方法是否重复!问题是我有两个路由方法
    api/controller/{label}
    api/controller/{parameter}
    ——它无法理解默认情况下使用哪一个。(或使用显式uri:
    api/controller?label=1
  • 重要提示:避免将许多复杂类型放入api方法中-为它们创建包装器并只放入一个参数 所有这些操作都允许我删除多余的属性,并使方法更具可读性

    结果如下:

    public IHttpActionResult PostOwner(OwnerWrapper modelWrapper)
    {
        string productCode = modelWrapper.Product.Code;
        Owner owner = modelWrapper.Owners[0];
    
        return CreatedAtRoute("DefaultApi", new { id = Owner.Id }, owner);
    }
    

    这只是一个测试用例,所以我们可以看到,
    productCode
    从未被使用过,但我的实际实现更困难。

    我使用以下步骤解决问题:

  • 删除控制器的所有
    [RoutePrefix]
    ——默认情况下让它们工作——它非常适合简单的请求
  • 重要提示:检查所有方法是否重复!问题是我有两个路由方法
    api/controller/{label}
    api/controller/{parameter}
    ——它无法理解默认情况下使用哪一个。(或使用显式uri:
    api/controller?label=1
  • 重要提示:避免将许多复杂类型放入api方法中-为它们创建包装器并只放入一个参数 所有这些操作都允许我删除多余的属性,并使方法更具可读性

    结果如下:

    public IHttpActionResult PostOwner(OwnerWrapper modelWrapper)
    {
        string productCode = modelWrapper.Product.Code;
        Owner owner = modelWrapper.Owners[0];
    
        return CreatedAtRoute("DefaultApi", new { id = Owner.Id }, owner);
    }
    

    这只是一个测试用例,所以我们可以看到,
    productCode
    从未被使用过,但我真正的实现更困难。

    错误发生在哪一行?能否提供堆栈跟踪?错误发生在哪一行?你能提供一个堆栈跟踪吗?谢谢你的贡献!读了你的答案,我找到了答案。答案是另一个,你不能给我,因为缺乏信息:)谢谢你的贡献!读了你的答案,我找到了答案。但答案是另一个,你不能给我,因为缺乏信息:)