目前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. Struts2文件上传(基于表单的文件上传)

    •Commons-FileUpload组件 –Commons是Apache开放源代码组织的一个Java子项目,其中的FileUpload是用来处理HTTP文件上传的子项目   •Commons-Fil ...

  2. ADO.NET学习系列(四)---窗体版的登录小程序

    1.需求分析:做一个登录的小程序,基于Winform的窗体小程序.基本要求:登录成功:弹框显示登录成功,登录失败就弹框显示失败. 扩展功能:登录次数超过3次,就”锁定“用户,提示登录错误次数过多,不能 ...

  3. win8.1注册表-修改资源管理器的默认路径regedit

    默认情况下,激活Win8的资源管理器都是直接打开库,对于习惯了以前版本的Windows用户来说,还要重新选择“计算机”才能进入相应的磁盘寻找文件,操作起来很是不便.为此,可以进行设置,让资源管理器默认 ...

  4. C#操作IIS程序池及站点的创建配置

    最近在做一个WEB程序的安装包:对一些操作IIS进行一个简单的总结:主要包括对IIS进行站点的新建以及新建站点的NET版本的选择,还有针对IIS7程序池的托管模式以及版本的操作:首先要对Microso ...

  5. C#的timer类

    在C#里关于定时器类就有3个 1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Timers.Timer类里 S ...

  6. 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop

    [源码下载] 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop 作者:weba ...

  7. windows下react-native环境搭建

    首先不得不先吐槽一下自己,一个坑总是踩很多次,且乐此不疲. 咋办? 写博客记录记录呗. 零.记录的点 Java环境的下载与配置 Android环境的下载与配置 Node环境的下载与配置 创建第一个re ...

  8. ugui 获取Text的高度,动态改变高度

    项目中需要根据聊天内容的多少.显示外边框的高度.因为Text的内容是不固定的.但宽度是固定的.高度根据文字多少自增 可以通过Text的属性preferredHeight 获取文本框的高度

  9. ThreadLocal解决线程安全问题

    一.线程安全问题产生的原因 线程安全问题都是由全局变量及静态变量引起的 二.线程安全问题 SimpleDateFormate sdf = new SimpleDateFormat();使用sdf.pa ...

  10. [moka同学笔记]Yii2.0 dropDownList的使用(二)

    方法一: <?php $psObjs = Poststatus::find()->all(); $allStatus = ArrayHelper::map($psObjs,'id','na ...