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-Type application/json; charset=utf-8


二、问题

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


三、解决方案

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

...
    
        
            
            
        
    
  

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


四、FromBodyBinder 的实现

FromBodyBinder 类实现

    /// 
    /// web api 动态参数绑定模型
    /// 解决脚本跨域访问问题
    /// 
    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 tcs = new TaskCompletionSource();
            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客户端写法





页面标题










你可能感兴趣的:(C#,WebFrom,C#,Asp.Net,MVC,C#,开发资料料,Javascript)