如何在控制器类中拥有多个Put动词

时间:2012-07-19 23:09:40

标签: c# asp.net-mvc asp.net-web-api

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

3 个答案:

答案 0 :(得分:5)

HTTP动词不是动作的名称,而是注释。

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

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

VERB 的位置为HttpDeleteHttpPostHttpPutHttpGet

希望这有帮助。

此致


更新:我的上述答案适用于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的匹配语义遵循以下规则

  1. 它将动作的名称与动词
  2. 相匹配
  3. 方法签名匹配(所以你可以有2个,1个无参数,其他带参数)
  4. 如果您的方法具有相同的动词和相同的签名,那么最好先调用定义的方法。

    我能理解你制作多种方法的理由,因为你必须一次更新一个盒子的单一。它可以通过以下方式实现。从客户端仅发送更新的值。例如,假设只改变了高度。所以将以下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);
    }