目前WebApi在使用上大部分都是跟MVC组合的,而且使用起来也确实十分便利。

但有时候我们也需要在WebForm中使用WebApi,二者还是有一定区别的。

首先看下结构

 ①ApiController

即Controller部分,当然也包含Api的路径也是很重要的。这里面是Api/{function}/{controller}/{action}

看一下Controller里面的内容

using System;
using System.Web.Http; namespace WebApiTest.Api.Func
{
public class TestController : ApiController
{
[HttpPost]
public TestModel Post([FromBody]TestModel model)
{
model.Name = "Post";
model.UpdatedOn = DateTime.Now;
model.Age++;
return model;
}
}
}

注意的地方有这么几点:

  • Controller要继承ApiController
  • Action要加上特性 [HttpPost] ,[HttpGet] 。。。如下图
  • 一般情况我们用的都是[HttpPost],这时候参数中就要加特性[FromBody]了
  • 为了能够直接使用请求过来的数据,而不必去转化成对应的实体类,我们需要给参数实体类加特性[Newtonsoft.Json.JsonObject]否则返回的数据会是酱紫的

这是使用的实体类

[Newtonsoft.Json.JsonObject]
public class TestModel
{
public string Name { set; get; } public int Age { set; get; } public DateTime UpdatedOn { set; get; }
}

②跨域处理程序CorsHandler.cs

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading;
using System.Net; namespace WebApiTest.Handler
{
public class CorsHandler : DelegatingHandler
{
const string Origin = "Origin";
const string AccessControlRequestMethod = "Access-Control-Request-Method";
const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
const string AccessControlAllowHeaders = "Access-Control-Allow-Headers"; protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
bool isCorsRequest = request.Headers.Contains(Origin);
bool isPreflightRequest = request.Method == HttpMethod.Options;
if (isCorsRequest)
{
if (isPreflightRequest)
{
return Task.Factory.StartNew<HttpResponseMessage>(() =>
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First()); string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
if (accessControlRequestMethod != null)
{
response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
} string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
if (!string.IsNullOrEmpty(requestedHeaders))
{
response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
} return response;
}, cancellationToken);
}
else
{
return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
{
HttpResponseMessage resp = t.Result;
resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
return resp;
});
}
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
}
}

CorsHandler.cs

③Controller配置程序 HttpControllerSelector.cs

 using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher; namespace WebApiTest.Handler
{
public class HttpControllerSelector : DefaultHttpControllerSelector
{
private HttpConfiguration configuration = null;
public HttpControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
this.configuration = configuration;
GetControllerMapping();
} public override string GetControllerName(HttpRequestMessage request)
{
object function, c;
var routedata = request.GetRouteData(); if (routedata.Values.TryGetValue("function", out function) &&
routedata.Values.TryGetValue("controller", out c))
{
var item = dict.FirstOrDefault(t => t.Key.Contains(string.Format("{0}.{1}controller", function, c).ToLower()));
if (item.Value != null)
{
return item.Value.ControllerName;
}
}
return base.GetControllerName(request);
} IDictionary<string, HttpControllerDescriptor> dict = new Dictionary<string, HttpControllerDescriptor>();
public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
var list = Assembly.GetAssembly(this.GetType()).GetTypes().Where(t => t.IsSubclassOf(typeof(ApiController)));
foreach (var type in list)
{
dict.Add(type.FullName.ToLower(), new HttpControllerDescriptor(this.configuration, type.FullName.ToLower(), type));
} return dict;
} public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
HttpControllerDescriptor c;
var cn = GetControllerName(request);
if (dict.TryGetValue(cn, out c))
{
return c;
}
return base.SelectController(request);
}
}
}

HttpControllerSelector.cs

④路由注册程序WebApiConfig.cs

 using System.Web.Http;
using System.Web.Http.Dispatcher; namespace WebApiTest.Handler
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
config.Services.Replace(typeof(IHttpControllerSelector), new HttpControllerSelector(config)); config.Routes.MapHttpRoute(
name: "Api",
routeTemplate: "api/{function}/{controller}/{action}"
);
}
}
}

WebApiConfig.cs

⑤Global.asax.cs

在该文件中添加如下代码

        public override void Init()
{
this.EndRequest += Global_EndRequest;
this.BeginRequest += Global_BeginRequest;
base.Init();
} protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
WebApiConfig.Register(GlobalConfiguration.Configuration);
}

至此 服务端的配置就基本OK了。

调用的地方用如下Ajax就可以了

$.ajax({
url: "api/func/Test/Post",
type: "POST",
data: {Name:"Ray"},
dataType:"json",
success: function (result) {
console.log(result);
}
});

代码下载


上面讲的是服务端的配置,顺带一提客户端的调用。

但是,如果是在后台调用某个WebApi该如何破呢?

我使用的是Intersoft的CrossLight,用起来也是比较简单。

TestModel model = new TestModel();
RestClient c = new RestClient("http://localhost:1234/API/Module/");
RestRequest req = new RestRequest("Function/Do", HttpMethod.POST);
req.RequestFormat = RequestDataFormat.Json;
req.AddBody(model);
var res = c.ExecuteAsync<WebApiModel>(req);
var tmp = JsonConvert.DeserializeObject<WebApiModel<TestModel>>(res.Result.Content).Model; if (res.Result.Data.HasError) {
throw new Exception(res.Result.Data.ErrorMessage);
}

这里面有个包装的类WebApiModel,是为了更好的传递其他信息(如错误信息),定义如下

using System;

namespace XX
{
[Newtonsoft.Json.JsonObject]
[Serializable]
public class WebApiModel
{
public WebApiModel()
{ } public WebApiModel(object model)
{
this.Model = model;
} public object Model { get; set; } public bool HasError
{
get
{
return !string.IsNullOrEmpty(ErrorMessage);
}
}
public string ErrorMessage { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace XX
{
[Newtonsoft.Json.JsonObject]
[Serializable]
public class WebApiModel<T>
{
public WebApiModel()
{ } public WebApiModel(T model)
{
this.Model = model;
} public T Model { get; set; } public bool HasError
{
get
{
return !string.IsNullOrEmpty(ErrorMessage);
}
}
public string ErrorMessage { get; set; }
}
}

Asp.Net实现WebApi跨域 (非MVC)的更多相关文章

  1. ASP.Net开发WebAPI跨域访问(CORS)的精简流程

    1: Web.config里有一行: <remove name="OPTIONSVerbHandler" /> 这个要删除. 2: nuget安装Microsoft.A ...

  2. 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式

    连表查询都用Left Join吧   最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...

  3. asp.net—WebApi跨域

    一.什么是跨域? 定义:是指浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制. 同源策略限制了以下行为: 1.Cookie.LocalStora ...

  4. WebAPI跨域处理

    原文来自:http://www.cnblogs.com/heifengwll/p/6243374.html WebApi2跨域问题   一.跨域问题产生的原因:同源策略(Same origin pol ...

  5. SNF快速开发平台MVC-EasyUI3.9之-WebApi跨域处理方案

    在做Web开发中,常常会遇到跨域的问题,到目前为止,已经有非常多的跨域解决方案.由于时间有限,本文不会深入. 笔者遇到的问题是Js调用WebAPI中的数据进行跨域的场景.涉及若干跨域方案:目前采用we ...

  6. C#进阶系列——WebApi 跨域问题解决方案:CORS

    前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨域问题一些细节. WebApi系列文章 C#进阶系列— ...

  7. WebApi 跨域问题解决方案:CORS

    注:本文为个人学习摘录,原文地址:http://www.cnblogs.com/landeanfen/p/5177176.html 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看W ...

  8. 关于WebApi 跨域问题的解决的方式

    最近在做WebApi 进行开发的时候 一直会遇到跨域方面的问题那么如何进行跨域问题其实非常的简单. 1.一直在使用WebApi的时候总是遇到跨域的问题 那么 什么是跨域?跨域,指的是浏览器不能执行其他 ...

  9. C#进阶系列——WebApi 跨域问题解决方案:CORS(转载)

    C#进阶系列——WebApi 跨域问题解决方案:CORS   阅读目录 一.跨域问题的由来 二.跨域问题解决原理 三.跨域问题解决细节 1.场景描述 2.场景测试 四.总结 正文 前言:上篇总结了下W ...

随机推荐

  1. Android 学习笔记之Volley开源框架解析(二)

    PS:Volley已经学完,可以安心的写一下博客总结一下了... 学习内容: 1.Request的完整封装... 2.RetryPolicy,DefaultRetryPolicy(请求重试策略源码解析 ...

  2. c# XML序列化与反序列化

    c# XML序列化与反序列化 原先一直用BinaryFormatter来序列化挺好,可是最近发现在WinCE下是没有办法进行BinaryFormatter操作,很不爽,只能改成了BinaryWrite ...

  3. java.lang.IllegalArgumentException 不合法的参数异常

    报错内容: IllegalArgumentException 不合法的参数异常 十二月 06, 2016 10:06:56 上午 org.apache.catalina.core.StandardWr ...

  4. linq之into子句

    在Linq表达式中,into子句可以创建一个临时标识符,使用该标识符可以存储group.join或select子句的结果. 下面实例中我们用GroupOtherQuery方法来演示group子句对结果 ...

  5. C#设计模式——外观模式(Facade Pattern)

    一.概述 在系统设计中,某一个系统可能非常庞大,用户要使用该系统就不得不掌握大量的接口,造成使用的不便.这时可以考虑将该系统细分成一系列子系统并使子系统间的耦合降到最低,利用外观模式提供一个外观对象, ...

  6. win 10 远程连接出现 "由于安全设置错误, 客户端无法连接到远程计算机. 确定你已登录到网络后.” 错误

    win 10 远程连接出现 "由于安全设置错误, 客户端无法连接到远程计算机. 确定你已登录到网络后.” 错误 解决方法如下: Step 1:打开"本地安全策略"- Wi ...

  7. Oracle级联查询

    在ORACLE 数据库中有一种方法可以实现级联查询   select  *                //要查询的字段 from table              //具有子接点ID与父接点I ...

  8. Python入门笔记(10):字典

    一.映射类型 我理解中的映射类型是:键值对的关系,键(key)映射值(value),且它们是一对多的关系.字典是Python唯一的映射类型. 扩展1:哈希表一种数据结构,值是根据相关的键进行数据存储的 ...

  9. jquery ajax跨域访问webservice配置

    1.webservice方法 [System.Web.Script.Services.ScriptService] public class TestService : System.Web.Serv ...

  10. 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar

    [源码下载] 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...