asp.net web api 解决ajax跨站点post请求提交 json 数据问题

asp.net web api 解决ajax跨站点post请求提交 json 数据问题


一、web api

web api 的 controller ,必须继承 apicontroller:

public class TestController : ApiController

action 可以使用参数绑定直接将 post 请求带的 json 转化为对象,如下:

public string TestMethod([FromBody]PersonInfo pars)

注:要达到这种参数绑定,客户端必须将 设置如下的 content-type 值

Content-Typeapplication/json; charset=utf-8


二、问题

如果客户端设置 content-type 为 application/json ,将导致405 拒绝访问的问题,也就是ajax跨站点请求问题


三、解决方案

1.设置web.config允许跨站点请求

...
    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Methods" value="GET,POST" />
        </customHeaders>
    </httpProtocol>
  </system.webServer>

2.重写参数绑定类 [FromBody] ,换成自己的 [FromBodyBinder]


四、FromBodyBinder 的实现

</pre></p><pre name="code" class="csharp" style="font-size:14px;">FromBodyBinder 类实现

    /// <summary>
    /// web api 动态参数绑定模型
    /// 解决脚本跨域访问问题
    /// </summary>
    public class FromBodyBinder : ParameterBindingAttribute
    {
        public override System.Web.Http.Controllers.HttpParameterBinding GetBinding(System.Web.Http.Controllers.HttpParameterDescriptor parameter)
        {
            return new FromBodyHttpParameterBinding(parameter);
        }
    }
    public class FromBodyHttpParameterBinding : HttpParameterBinding
    {
        public FromBodyHttpParameterBinding(HttpParameterDescriptor des)
            : base(des)
        {
            _parsType = des.ParameterType;
        }

        private Type _parsType;
        private struct AsyncVoid { }
        public override Task ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
            //读取post内容
            var task = actionContext.Request.Content.ReadAsStreamAsync();
            var content = string.Empty;
            var sm = task.Result;
            sm.Seek(0, SeekOrigin.Begin);
            var bytes = sm.ToByteArray();
            content = bytes.ToStr(System.Text.Encoding.UTF8);
            var obj = content.ToJsonDeserialize(_parsType);

            SetValue(actionContext, obj);

            TaskCompletionSource<AsyncVoid> tcs = new TaskCompletionSource<AsyncVoid>();
            tcs.SetResult(default(AsyncVoid));
            return tcs.Task;
        }
    }

用到一个扩展方法 ToJsonDeserialize(),实现如下

        public static object ToJsonDeserialize(this string str,Type type)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(str))
                {
                    return null;
                }
                var serialize = new JavaScriptSerializer();
                //针对日期序列化时区的转化
                str = Regex.Replace(str, @"\\/Date\((-?\d+)\)\\/", match =>
                {
                    var dt = new DateTime(1970, 1, 1);
                    dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value));
                    dt = dt.ToLocalTime();
                    return dt.ToString("yyyy-MM-dd HH:mm:ss");
                });
                return serialize.Deserialize(str, type);
            }
            catch (Exception ex)
            {
               
                return null;
            }
        }


五、测试代码部分

5.1 服务器代码

    public class TestController : ApiController
    {
        public class PersonInfo
        {
            public int id { set; get; }
            public string name { set; get; }
            public DateTime create_time { set; get; }
        }

        public string TestMethod([FromBodyBinder]PersonInfo pars)
        //public string TestMethod([FromBody]PersonInfo pars) web api  的写法
        {
            var result = new
            {
                receive_time=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") ,
                data=pars
            };
            return result.ToJsonSerialize();
        }
    }

5.2客户端写法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>页面标题</title>
</head>
<script src="zepto.js"></script>

<body>
<input type="button" id="btn" value="type=button" />

</body>
<script>
    $(function(){
        $("#btn").click(function(){
			var reqdata={
				id:"111",
				name:"张三",
				create_time:"2012-12-12 12:12:12"
			};
           var reqdatajson = JSON.stringify(reqdata);
            alert("请求内容:"+reqdatajson);      
			var url="http://www.xxx.com/Test/TestMethod";
            $.ajax({               
               url:url,
                data: reqdatajson,
                dataType: "json", 
                type: "POST",
                success:function(d){
                    alert("响应内容:"+JSON.stringify(d))
                },
                error:function(r,s,m){
                    console.log(r+"---"+s+"-----------"+m)
                }                 
            });
        });
    });
    </script>
</html>


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值