WebAPI服务中的批处理请求支持



我已经在webapiconfig.cs

中注册了批处理WebAPI和WebAPI服务
config.Routes.MapHttpBatchRoute(
                routeName: "WebApiBatch",
                routeTemplate: "api/$batch",
                batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer));
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

和WebAPI服务如下

员工班级

public class Employee
    {
        public int EmployeeID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Employee()
        {
        }
        public Employee(int id, string LN, string FN)
        {
            this.EmployeeID = id;
            this.LastName = LN;
            this.FirstName = FN;
        }
    }

员工接口

interface IEmployeeRepository
    {
        IEnumerable<Employee> GetAll();
        Employee Get(int EmployeeID);
        Employee Add(Employee emp);
        void Remove(int EmployeeID);
        bool Update(Employee emp);
    }

员工存储库

public class EmployeeRepository : IEmployeeRepository
    {
        private List<Employee> emp = new List<Employee>();
        public EmployeeRepository()
        {
            emp.Add(new Employee(1, "Davolio", "Nancy"));
            emp.Add(new Employee(2, "Fuller", "Andrew"));
            emp.Add(new Employee(3, "Leverling", "Janet"));
            emp.Add(new Employee(4, "Peacock", "Margaret"));
            emp.Add(new Employee(5, "Buchanan", "Steven"));
        }
        public IEnumerable<Employee> GetAll()
        {
            return emp;
        }
        public Employee Get(int id)
        {
            return emp.Find(p => p.EmployeeID == id);
        }
        public Employee Add(Employee eObj)
        {
            if (eObj == null)
            {
                throw new ArgumentNullException("eObj");
            }
            emp.Add(eObj);
            return eObj;
        }
        public void Remove(int id)
        {
            emp.RemoveAll(p => p.EmployeeID == id);
        }
        public bool Update(Employee eObj)
        {
            if (eObj == null)
            {
                throw new ArgumentNullException("eObj");
            }
            int index = emp.FindIndex(p => p.EmployeeID == eObj.EmployeeID);
            if (index == -1)
            {
                return false;
            }
            emp.RemoveAt(index);
            emp.Add(eObj);
            return true;
        }
    }

WebAPI控制器

public class EmployeeController : ApiController
    {
        static readonly IEmployeeRepository repository = new EmployeeRepository();
        // GET api/<controller>
        [HttpGet]
        public object Get()
        {

            var queryString = HttpContext.Current.Request.QueryString;
            var data = repository.GetAll().ToList();
            return new { Items = data, Count = data.Count() };
        }
        public Employee GetEmployee(int id)
        {
            Employee emp = repository.Get(id);
            if (emp == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return emp;
        }
        // POST api/<controller>
        public HttpResponseMessage PostEmployee(Employee emp)
        {
            emp = repository.Add(emp);
            var response = Request.CreateResponse<Employee>(HttpStatusCode.Created, emp);
            string uri = Url.Link("Employee", new { id = emp.EmployeeID });
            response.Headers.Location = new Uri(uri);
            return response;
        }
         [HttpPut]
        // PUT api/<controller>
        public void PutEmployee(Employee emp)
        {
            if (!repository.Update(emp))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }
        [HttpDelete]
         public void Delete(int id)
        {
          //  int empID = int32
            Employee emp = repository.Get(id);
            if (emp == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            repository.Remove(id);
        }
    }

我已经从客户端提出了AJAX请求,以便访问服务我已经在Ajax的数据字段中设置了批处理请求

--batch_ec79f662-862e-4016-a19a-1dbff86d7120
Content-Type: multipart/mixed; boundary=changeset_eb327bfc-5424-47b6-becf-416c43e13899
--changeset_eb327bfc-5424-47b6-becf-416c43e13899
Content-Type: application/http
Content-Transfer-Encoding: binary 
POST /api/Employee HTTP/1.1
Content-Id: 0
Content-Type: application/json; charset=utf-8 
{"EmployeeID":6,"FirstName":"angel","LastName":"dsfs"}
--changeset_eb327bfc-5424-47b6-becf-416c43e13899
Content-Type: application/http
Content-Transfer-Encoding: binary 
PUT /api/Employee HTTP/1.1
Content-Id: 1
Content-Type: application/json; charset=utf-8 
{"EmployeeID":2,"FirstName":"kalai","LastName":"selvi"}

--changeset_eb327bfc-5424-47b6-becf-416c43e13899
Content-Type: application/http
Content-Transfer-Encoding: binary 
PUT /api/Employee HTTP/1.1
Content-Id: 2
Content-Type: application/json; charset=utf-8 
{"EmployeeID":3,"FirstName":"Janet","LastName":"Leverling"}

--changeset_eb327bfc-5424-47b6-becf-416c43e13899
Content-Type: application/http
Content-Transfer-Encoding: binary 
DELETE /api/Employee(3) HTTP/1.1
Content-Id: 3
Content-Type: application/json; charset=utf-8 
--changeset_eb327bfc-5424-47b6-becf-416c43e13899--
--batch_ec79f662-862e-4016-a19a-1dbff86d7120--

和整个AJAX请求

$.ajax{
Content-type: "multipart/mixed; charset=UTF-8;boundary=batch_ec79f662-862e-4016-a19a-1dbff86d7120",
data:"--batch_ec79f662-862e-4016-a19a-1dbff86d7120↵Content-Type: multipart/mixed; boundary=changeset_eb327bfc-5424-47b6-becf-416c43e13899↵↵--changeset_eb327bfc-5424-47b6-becf-416c43e13899↵Content-Type: application/http↵Content-Transfer-Encoding: binary ↵↵POST /api/Employee HTTP/1.1↵Content-Id: 0↵Content-Type: application/json; charset=utf-8 ↵↵{"EmployeeID":6,"FirstName":"angel","LastName":"dsfs"}↵↵--changeset_eb327bfc-5424-47b6-becf-416c43e13899↵Content-Type: application/http↵Content-Transfer-Encoding: binary ↵↵PUT /api/Employee HTTP/1.1↵Content-Id: 1↵Content-Type: application/json; charset=utf-8 ↵↵{"EmployeeID":2,"FirstName":"kalai","LastName":"selvi"}↵↵↵--changeset_eb327bfc-5424-47b6-becf-416c43e13899↵Content-Type: application/http↵Content-Transfer-Encoding: binary ↵↵PUT /api/Employee HTTP/1.1↵Content-Id: 2↵Content-Type: application/json; charset=utf-8 ↵↵{"EmployeeID":3,"FirstName":"Janet","LastName":"Leverling"}↵↵↵--changeset_eb327bfc-5424-47b6-becf-416c43e13899↵Content-Type: application/http↵Content-Transfer-Encoding: binary ↵↵DELETE /api/Employee(3) HTTP/1.1↵Content-Id: 3↵Content-Type: application/json; charset=utf-8 ↵↵--changeset_eb327bfc-5424-47b6-becf-416c43e13899--↵--batch_ec79f662-862e-4016-a19a-1dbff86d7120--",
type:"POST",
url:"/api/Employee"
}

提出请求后,我得到了一个异常消息

1.  {Message: "The request entity's media type 'multipart/mixed' is not supported for this resource.",…}
1.  ExceptionMessage:"No MediaTypeFormatter is available to read an object of type 'Employee' from content with media type 'multipart/mixed'."
2.  ExceptionType:"System.Net.Http.UnsupportedMediaTypeException"
3.  Message:"The request entity's media type 'multipart/mixed' is not supported for this resource."
StackTrace:"   at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
↵   at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
↵   at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"

我在哪里犯了错误

确保您调用所配置的实际批处理路由,而不是直接在amploeecontroller上的端点。当您这样做时(我看到您的Ajax调用具有URL:"/api/雇员"(,则您将收到该消息,因为这些端点不支持混合模式。如果您改用批处理路由(/api/batch(,则应该解决问题。我使用的端点没有美元符号,但是我将其配置为API/批次:

                routeName: "batch",
            routeTemplate: "api/batch",