无法接受XDomainRequest POST到WebAPI

时间:2013-11-05 16:17:22

标签: json post asp.net-web-api xdomainrequest

我有一个控制器类,我可以在API上启动Get调用,但是当我尝试POST命令时,我得到HTTP / 1.1 415不支持的媒体类型

有什么地方我必须允许POST吗?我把[HttpPost]放在方法前面,但没有运气。

public class initController : ApiController
{
    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/<controller>
    [HttpPost]
    public string Post([FromBody]string value)
    {
        oTree myT = new oTree();
        myT.build(0);
        myT.entity.question = value;
        return JsonConvert.SerializeObject(myT);
    }

    // PUT api/<controller>/5
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/<controller>/5
    public void Delete(int id)
    {
    }
}

Javscript邮政编码:

function gpRequest(service, verb, oData, callback) {
if (bool_cantransmit) {
    bool_cantransmit = false;
    var xdr;
    var url = base_service_url + service + "/";
    if (window.XDomainRequest) // Check whether the browser supports XDR. 
    {
        xdr = new XDomainRequest(); // Create a new XDR object.
        if (xdr) {
            xdr.onerror = errorHandler;
            xdr.onload = callback;
            xdr.contentType = "application/json";
            xdr.open(verb, url);
            xdr.send(oData);
        }
    } else {
        var xhr = new XMLHttpRequest();
        xhr.onerror = errorHandler;
        xhr.onload = callback;

        xhr.open(verb, url, true);
        xhr.send(oData);
    }
}

}

2 个答案:

答案 0 :(得分:6)

在遇到类似问题后,我决定将其写下来以供将来参考。

XDomainRequest的问题在于它没有添加Content-Type标头。 这意味着Content-Type默认为application/octet-stream,没有默认MediaTypeFormatters。这会导致API拒绝415 Unsupported Media Type的请求。

一种可能的解决方法是假设application/octet-streamapplication/json

创建一个源自OctetStreamMediaFormatter但又接受JsonMediaTypeFormatter的新application/octet-stream

public class OctetStreamMediaFormatter : JsonMediaTypeFormatter
{
    public OctetStreamMediaFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
    }
}

将新格式化程序添加到您的配置中(例如Global.asax.cs

GlobalConfiguration.Configuration.Formatters.Add(new OctetStreamMediaFormatter());

ApiController装饰适当的方法:

[HttpPost]
[EnableCors(origins: "*", headers: "*", methods: "POST")]
public HttpResponseMessage ExampleAction(ExampleModel model)
{
    if (ModelState.IsValid)
    {
        ...
    }
    ...
}

[EnableCors(...)]会在响应中添加所需的Access-Control-Allow-Origin标头。启用CORS(例如在WebApiConfig.cs中):

config.EnableCors();

现在应该可以使用XDomainRequest发送和接收数据。

function xdr(json) {

    if (!window.XDomainRequest) {
        console.log("Sorry, XDomainRequest not supported");
        return;
    }

    var xdr = new XDomainRequest();
    xdr.onerror = function () {
        console.log("Sorry, XDomainRequest.onerror()");
    };
    xdr.onload = function () {
        console.log(xdr.responseText);
    };
    xdr.open("POST", "ExampleApiController/ExampleAction");
    xdr.send(json);

}

答案 1 :(得分:0)

好吧,value=Test不是有效的json。您可以发送json格式,因为您已将application/json设置为content-type标头请求属性,示例为:

gpRequest(service, 'POST', "{ Value: 'Test' }", callback);

在服务器端,尝试创建DTO对象:

public class MessageDTO
{
   public string Value { get; set; }
}

并加入post方法:

[HttpPost]
public string Post([FromBody]MessageDTO message)
{
    oTree myT = new oTree();
    myT.build(0);
    myT.entity.question = message.Value;
    return JsonConvert.SerializeObject(myT);
}