通过扩展让ASP.NET Web API支持JSONP
2013-12-06 12:33
447 查看
通过扩展让ASP.NET Web API支持JSONP
[code] public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
{
public string Callback{ get; private set;}
public JsonpMediaTypeFormatter(string callback = null)
{
this.Callback = callback;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if (string.IsNullOrEmpty(this.Callback))
{
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
try
{
this.WriteToStream(type, value, writeStream, content);
return Task.FromResult<AsyncVoid>(new AsyncVoid());
}
catch (Exception exception)
{
TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>();
source.SetException(exception);
return source.Task;
}
}
private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings);
using(StreamWriter streamWriter = new StreamWriter(writeStream, this.SupportedEncodings.First()))
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter){ CloseOutput = false})
{
jsonTextWriter.WriteRaw(this.Callback + "(");
serializer.Serialize(jsonTextWriter, value);
jsonTextWriter.WriteRaw(")");
}
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
if (request.Method != HttpMethod.Get)
{
return this;
}
string callback;
if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key,
pair => pair.Value).TryGetValue("callback", out callback))
{
return new JsonpMediaTypeFormatter(callback);
}
return this;
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private struct AsyncVoid
{}
}
[/code]
[/code]
我们重写了GetPerRequestFormatterInstance方法,在默认情况下,当ASP.NET Web API采用内容协商机制选择出与当前请求相匹配的MediaTypeFormatter后,会调用此方法来创建真正用于序列化响应结果的MediaTypeFormatter对象。在重写的这个GetPerRequestFormatterInstance方法中,我们尝试从请求的URL中得到携带的JavaScript回调函数名称,即一个名为“callback”的查询字符串。如果回调函数名不存在,则直接返回自身,否则返回据此创建的JsonpMediaTypeFormatter对象。
[code]public class ContactsController : ApiController
{
public IEnumerable<Contact> GetAllContacts()
{
Contact[] contacts = new Contact[]
{
new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},
new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},
};
return contacts;
}
}
public class Contact
{
public string Name{ get; set;}
public string PhoneNo{ get; set;}
public string EmailAddress{ get; set;}
}
[/code]
[/code]
现在我们在WebApi应用的Global.asax中利用如下的程序创建这个JsonpMediaTypeFormatter对象并添加当前注册的MediaTypeFormatter列表中。为了让它被优先选择,我们将这个JsonpMediaTypeFormatter对象放在此列表的最前端。
[code] [code] public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter ());
//其他操作
}
}
[/code]
[/code]
接下来们在MvcApp应用中定义如下一个HomeController,默认的Action方法Index会将对应的View呈现出来。
[code] [code] public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
[/code]
[/code]
如下所示的是Action方法Index对应View的定义。我们的目的在于:当页面成功加载之后以Ajax请求的形式调用上面定义的Web API获取联系人列表,并将自呈现在页面上。如下面的代码片断所示,我们直接调用$.ajax方法并将dataType参数设置为“jsonp”。
[code] [code] <html>
<head>
<title>联系人列表</title>
<script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
</head>
<body>
<ul id="contacts"></ul>
<script type="text/javascript">
$(function ()
{
$.ajax({
Type : "GET",
url: "http://localhost:3721/api/contacts",
dataType : "jsonp",
success: listContacts
});
});
function listContacts(contacts){
$.each(contacts, function (index, contact){
var html = "<li><ul>";
html += "<li>Name: " + contact.Name + "</li>";
html += "<li>Phone No:" + contact.PhoneNo + "</li>";
html += "<li>Email Address: " + contact.EmailAddress + "</li>";
html += "</ul>";
$("#contacts").append($(html));
});
}
</script>
</body>
</html>
[/code]
[/code]
直接运行该ASP.NET MVC程序之后,会得到如下图所示的输出结果,通过跨域调用Web API获得的联系人列表正常地显示出来。
[code] GET http://localhost:3721/api/contacts?callback=jQuery110205729522893670946_1386232694513 &_=1386232694514 HTTP/1.1
Host: localhost:3721
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Referer: http://localhost:9527/[/code]Accept-Encoding: gzip,deflate,sdchHTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheContent-Type: application/json; charset=utf-8Expires: -1Server: Microsoft-IIS/8.0X-AspNet-Version: 4.0.30319X-SourceFiles: =?UTF-8?B?RTpc5oiR55qE6JGX5L2cXEFTUC5ORVQgV2ViIEFQSeahhuaetuaPreenmFxOZXcgU2FtcGxlc1xDaGFwdGVyIDE0XFMxNDAzXFdlYkFwaVxhcGlcY29ud?=X-Powered-By: ASP.NETDate: Thu, 05 Dec 2013 08:38:15 GMTContent-Length: 248jQuery110205729522893670946_1386232694513([{"Name":"张三","PhoneNo":"123","EmailAddress":"zhangsan@gmail.com"},{"Name":"李四","PhoneNo":"456","EmailAddress":"lisi@gmail.com"},{"Name":"王五","PhoneNo":"789","EmailAddress":"wangwu@gmail.com"}])
[/code]
[/code]
相关文章推荐
- 通过扩展让ASP.NET Web API支持JSONP
- 通过扩展让ASP.NET Web API支持JSONP -摘自网络
- (转)通过扩展让ASP.NET Web API支持JSONP
- 通过扩展让ASP.NET Web API支持JSONP
- 通过扩展让ASP.NET Web API支持JSONP ----- .NET 4.0 asp.net WebApi(不是WebApi 2)
- [CORS:跨域资源共享] 通过扩展让ASP.NET Web API支持JSONP
- 通过扩展让ASP.NET Web API支持JSONP
- [CORS:跨域资源共享] 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 通过扩展让ASP.NET Web API支持W3C的CORS规范(转载)
- 通过微软的cors类库,让ASP.NET Web API 支持 CORS
- [翻译]在ASP.NET Web API中通过OData支持查询和分页
- 通过微软的cors类库,让ASP.NET Web API 支持 CORS
- 通过微软的cors类库,让ASP.NET Web API 支持 CORS
- ASP.NET Web API自身对CORS的支持: CORS授权检验的实施
- ASP.NET Web API自身对CORS的支持:从实例开始
- [Asp.netAjaxToolkit扩展]Calendar支持时间段
- [转]让ASP.NET Web API支持$format参数的方法