C# 路由属性名称属性
我有ProductsController和OwnersController: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
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
从未被使用过,但我真正的实现更困难。错误发生在哪一行?能否提供堆栈跟踪?错误发生在哪一行?你能提供一个堆栈跟踪吗?谢谢你的贡献!读了你的答案,我找到了答案。答案是另一个,你不能给我,因为缺乏信息:)谢谢你的贡献!读了你的答案,我找到了答案。但答案是另一个,你不能给我,因为缺乏信息:)