WebApi ActionName 删除路由不起作用

WebApi ActionName delete route not working

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

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

因为我已经映射了 ControllerAndActionAndId 路由,所以无法调用 "normal" 控制器的删除路由(示例:Contactscontroller)。
所有路由除了删除路线外都在工作。

StatusCode: 404, ReasonPhrase: 'Not Found'

通常有一个 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();
            }
        }
    }

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

如果您使用 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。

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

        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
            }
        );

太简单了..非常感谢!