【问题标题】:WebApi ActionName delete route not workingWebApi ActionName 删除路由不起作用
【发布时间】:2020-02-10 09:27:41
【问题描述】:

我的项目包含多个 WebApi 控制器,每个控制器通常提供三个操作:get(guid)、post(data) 和 delete(guid),
WebApiconfig 中针对此要求描述了默认路由。 (姓名:ControllerAndId

现在我必须实现一个控制器,它必须处理不同的发布操作。为此,我尝试使用ActionNames 映射另一条路线。 (姓名:ControllerAndActionAndId

由于我已经映射了ControllerAndActionAndId 路由,因此无法调用“普通”控制器的删除路由(例如:Contactscontroller)。
除了删除路由之外,所有路由都正常工作。

状态码:404,原因短语:'未找到'

有一个通常是ApiController的例子:

    public class ContactsController : ApiController
{
    public IEnumerable<Contact> Get()
    {
        return GetContacts();
    }

    public HttpResponseMessage Post(Contact contact)
    {            
        SaveContact(contact);

        return Request.CreateResponse<Guid>(_code, contact.Id);
    }

    public void Delete(Guid id)
    {
        DeleteContact(id);
    }
}

带有 ActionName-Route 的控制器:

    public class AttachmentsController : ApiController
{
    [HttpGet]
    public Attachment Get(Guid attachmentId)
    {
        return GetAttachment(attachmentId);
    }

    [HttpPost]
    [ActionName("save")]
    public HttpResponseMessage Save(AttachmentSaveData saveData)
    {
        SaveAttachment(saveData);
    }

    [HttpPost]
    [ActionName("remove")]
    public HttpResponseMessage Remove(AttachmentDeleteData deleteData)
    {
       DeleteAttachment(deleteData);            
    }
}

WebApiConfig:

            // Web API routes
        config.MapHttpAttributeRoutes();

        // Controller with ID
        // To handle routes like `/api/VTRouting/route/1`
        config.Routes.MapHttpRoute(
            name: "ControllerAndActionAndId",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new
            {
                id = RouteParameter.Optional,
                action = RouteParameter.Optional
            }
        );

        // Controller with ID
        // To handle routes like `/api/VTRouting/1`
        config.Routes.MapHttpRoute(
            name: "ControllerAndId",
            routeTemplate: "api/{controller}/{id}",
            defaults: new
            {
                id = RouteParameter.Optional
            }
        );

ClientAction 删除函数:

        private void Delete(string uri, int id)
    {
        using (HttpClient _client = new HttpClient())
        {
            _client.BaseAddress = BaseAddress;
            string _url = string.Format("{0}/{1}", uri, id);
            var _response = _client.DeleteAsync(_url).Result;

            if (!_response.IsSuccessStatusCode)
            {
                throw new Exception();
            }
        }
    }

我目前不知道如何解决这个问题。

【问题讨论】:

  • 尝试使用[HttpDelete] 而不是[HttpPost] 进行“删除”操作
  • DeleteAsync 方法发送 DELETE 请求。但是你有 POST 方法
  • AttachmentController 现在工作正常。但是 ContactController 的 DELETE 操作不再起作用了。
  • 添加 HttpDelete 属性以删除操作

标签: c# webapi


【解决方案1】:

如果您使用 Web API,则需要在操作中添加 HTTP 动词。

例如,您的代码必须如下:

public class ContactsController : ApiController
{ 
    [HttpGet]
    public IEnumerable<Contact> Get()
    {
        return GetContacts();
    }

    [HttpPost]
    public HttpResponseMessage Post(Contact contact)
    {            
        SaveContact(contact);

        return Request.CreateResponse<Guid>(_code, contact.Id);
    }

    [HttpDelete]
    public void Delete(Guid id)
    {
        DeleteContact(id);
    }
}

注意删除操作

  1. 如果您在操作中使用 HttpDelete 动词,则必须从您的客户端 httpClient.DeleteAsync(...) 发送删除请求。
  2. 如果您在操作上使用 HttpPost 动词,则必须从您的客户端 httpClient.PostAsync(...) 发送 post 请求。

AttachmentsController 类似于 ContactsController。

【讨论】:

    【解决方案2】:

    我非常关注控制器的动作和路线。 但是在客户端很容易找到解决方案:

            private void Delete<T>(string uri, T value)
        {
            using (HttpClient _client = new HttpClient())
            {
                _client.BaseAddress = BaseAddress;
                _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                string _url = string.Format("{0}/{1}", uri, value);
                var _response = _client.DeleteAsync(_url).Result;
            }
        }
    

    这个方案只需要WebApiConfig中的一个路由:

                config.Routes.MapHttpRoute(
                name: "ControllerAndId",
                routeTemplate: "api/{controller}/{id}",
                defaults: new
                {
                    id = RouteParameter.Optional
                }
            );
    

    太容易了..非常感谢!

    【讨论】:

      猜你喜欢
      • 2017-01-26
      • 2016-04-12
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      • 2021-05-17
      • 1970-01-01
      • 2016-05-10
      相关资源
      最近更新 更多