我正在使用ASP.NET Web API和控制器类来处理来自客户端的JSON数据。我遇到过单个控制器需要多个Put方法的情况。
示例:
我可以拥有一个我的客户
var box = {size:2,color:'red',height:45,width:12}
现在,如果我想更新整个盒子对象,我可以做一个
public void Put(Box box)
{
}
好的,我得到了这么多。
但我需要能够更新框的单个值,如下所示:
public void Put(int id, width value)
{
}
public void Put(int id, height value)
{
}
public void Put(int id, color value)
{
}
我如何在with .net c#controller中添加额外的Put动词?
我将为刚刚创建的赏金添加更多代码。我需要有人向我展示如何制作我正在提供工作的代码。我需要将多个方法映射到一个httpVERB PUT
。原因是我需要微服务器上的更新项目。就像名字一样,我不想通过线路发送大型对象来更新一个字段,因为我的程序也将连接到移动设备。
---此代码不起作用,只返回PutName
而不返回PutBrand
。我已经以你能想象到的方式切换了签名。
[AcceptVerbs("PUT")]
[ActionName("PutBrand")]
public HttpResponseMessage PutBrand(int id, int val)
{
return Request.CreateResponse(HttpStatusCode.Created, "Brand");
}
[AcceptVerbs("PUT")]
[ActionName("PutName")]
public HttpResponseMessage PutName(IDString idString)
{
return Request.CreateResponse(HttpStatusCode.Created, "Name");
}
public class IDString
{
public IDString() { }
public int ID { get; set; }
public string Value { get; set; }
}
----客户端
$.ajax(
{
url: "/api/project",
type: "PUT",
data: JSON.stringify({ id: 45, val:'xxx' }),
contentType: "application/json",
success: function (result) {
}
});
---路线配置
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
提议的解决方案
$.ajax(
{
url: "/api/project?a=name",
type: "PUT",
$.ajax(
{
url: "/api/project?a=brand",
type: "PUT",
$.ajax(
{
url: "/api/project?a=size",
type: "PUT",
当然我会在a = myJavaScriptVariable
的位置使用变量 public HttpResponseMessage Put(Project project)
{
string update = HttpContext.Current.Request.QueryString["a"];
switch (update)
{
case "name":
break;
case "brand":
break;
case "size":
break;
default:
break;
}
return Request.CreateResponse(HttpStatusCode.Accepted);
}
答案 0 :(得分:5)
HTTP动词不是动作的名称,而是注释。
这样,您的控制器应如下所示:
[VERB]
public ActionResult SomeMeaningfulName(ARGUMENTS)
{
//...
}
VERB 的位置为HttpDelete
,HttpPost
,HttpPut
或HttpGet
希望这有帮助。
此致
更新:我的上述答案适用于ASP.NET MVC应用。但是,如果我们讨论的是 WebAPI 应用程序,那么还有另一个选项可以设置操作的动词:WebAPI使用了解操作名称的约定作为动词,只要它是一个有效的HTTP动词。 该操作甚至可能具有有意义的名称,但必须以动词开头。 更多信息at this post。
感谢@Anand指出这一点(并努力让我理解=))。
答案 1 :(得分:2)
您可以使用ActionName属性,以便可以使用相同的名称调用具有此属性的所有操作。
[ActionName("Put")]
public void PutWidth(int id, width value)
{
}
[ActionName("Put")]
public void PutHeight(int id, height value)
{
}
[ActionName("Put")]
public void PutColor(int id, color value)
{
}
答案 2 :(得分:0)
老实说,你的解决方案转向RPC编码风格而不是Rest Style编码。
首先考虑您的网址以执行CRUD功能。
<强> “/盒/(编号)”强>
这应该足以完成您的所有CRUD功能。此外,Web API的匹配语义遵循以下规则
如果您的方法具有相同的动词和相同的签名,那么最好先调用定义的方法。
我能理解你制作多种方法的理由,因为你必须一次更新一个盒子的单一。它可以通过以下方式实现。从客户端仅发送更新的值。例如,假设只改变了高度。所以将以下Box对象发送到服务器
//send only Id and height
var data = {size:null,color:null,height:45,width:null,id: 91}
$.ajax(
{
url: "/api/project",
type: "PUT",
data: JSON.stringify(data),
contentType: "application/json",
success: function (result) {
}
});
在服务器上检查哪些字段在更新之前为空。我的代码假设您正在使用实体框架工作,但它对任何数据库都是相同的。
public void Put(Box box)
{
//fetch the item from DB
var item = _db.Box.First(i => i.id = box.id);
if(item == null)
// If you can't find the box to update
throw new HttpResponseException(HttpStatusCode.NotFound);
//check for properties if not null
if(box.height != null)
item.height= box.height;
if(box.width!= null)
item.width= box.width;
if(box.color!= null)
item.color= box.color;
if(box.size!= null)
item.size= box.size;
//update the item in database
_db.SaveChanges();
return new HttpResponseMessage<Box>(HttpStatusCode.Accepted);
}