1

我正在使用 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)
    {

    }

我将如何在我的 .net c# 控制器中映射额外的 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);
    }
4

3 回答 3

5

HTTP 动词不是动作的名称,它是一个注解。

这样,您的控制器应如下所示:

[VERB]
public ActionResult SomeMeaningfulName(ARGUMENTS)
{
//...
}

VERB是, ,或_HttpDeleteHttpPostHttpPutHttpGet

希望这可以帮助。

问候


更新:我上面的答案对于 ASP.NET MVC 应用程序是正确的。但是,如果我们谈论的是WebAPI应用程序,那么还有另一个选项来设置动作的动词:WebAPI 使用将动作名称理解为动词的约定,只要它是有效的 HTTP 动词。动作甚至可以有一个有意义的名称,但它必须以动词开头。更多信息在这篇文章

感谢@Anand 指出这一点(以及让我理解的努力=))。

于 2012-07-19T23:20:11.587 回答
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)
    {

    }
于 2012-07-19T23:24:52.187 回答
0

老实说,您的解决方案转向 RPC 编码风格,而不是 Rest 编码风格。

首先考虑您的 URL 以执行 CRUD 功能。

“/盒子/{id}”

这应该足以完成所有 CRUD 功能。此外,Web API 的匹配语义遵循以下规则

  1. 它将动作的名称与动词相匹配
  2. 匹配方法签名(因此您可以拥有 2 个 get 、1 个无参数和其他带参数)

如果您有具有相同动词和相同签名的方法,那么充其量,首先定义的方法会被调用。

我可以理解您为 put 制作多种方法的原因,因为您必须一次更新一个 box 属性。它可以通过以下小技巧来实现。从客户端仅发送更新的值。例如,假设仅更改高度。所以将以下 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);
}
于 2012-07-23T06:10:38.887 回答