اگر یک API Restful با استفاده از ASP.NET Web API ایجاد کردهاید و اگر API شما در یک دامنه و UI در دامنه دیگری است، ممکن است به دلیل مشکلات بین دامنهای با خطا مواجه شوید.
- گزینه ها http://localhost:5000/api/ 404 (یافت نشد).
- XMLHttpRequest نمی تواند http://localhost:5000/api/ بارگیری شود . هیچ عنوان «Access-Control-Allow-Origin» در منبع درخواستی وجود ندارد. بنابراین، منبع " http://localhost:54317 " مجاز به دسترسی نیست. پاسخ دارای کد وضعیت HTTP 404 بود.
به عبارت دیگر، شما نمی توانید از طریق بخش جلویی خود که در دامنه دیگری میزبانی شده است، با WebAPI تماس بگیرید.
بنابراین باید از JSONP برای دریافت داده با استفاده از AJAX استفاده کنید، نه با JSON.
برای رسیدن به این هدف باید JsonpMediaTypeFormatter را نصب کنید.
برای نصب JsonpMediaTypeFormatter در ویژوال استودیو، JsonpMediaTypeFormatter را در "Manage NuGet Packages" جستجو کنید و آن را نصب کنید.
سپس می توانید در منابع پروژه خود مشاهده کنید که یک DLL جدید اضافه شده است.
WebApiContrib.Formatting.Jsonp.dll
برای استفاده از این DLL باید متد Application_Start() را در فایل Global.asax.cs تغییر دهید.
- using WebApiContrib.Formatting.Jsonp;
- using System.Net.Http.Formatting;
- GlobalConfiguration.Configuration.Formatters.Clear();
- GlobalConfiguration.Configuration.Formatters.Add(new JsonpMediaTypeFormatter(new JsonMediaTypeFormatter()));
یا می توانید از کد JsonMediaTypeFormatter استفاده کنید، باید این کد را در پوشه App_Start بنویسید و این کد را در Application_Start() ثبت کنید.
کد JsonMediaTypeFormatter:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Net.Http.Formatting;
- using System.Net.Http.Headers;
- using System.Net.Http;
- using Newtonsoft.Json.Converters;
- using System.IO;
- using System.Net;
- using System.Threading.Tasks;
- namespace WebAPI
- {
- /// <summary>
- /// Handles JsonP requests when requests are fired with text/javascript
- /// </summary>
- public class JsonpFormatter : JsonMediaTypeFormatter
- {
- public JsonpFormatter()
- {
- SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
- SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
- JsonpParameterName = "callback";
- }
- /// <summary>
- /// Name of the query string parameter to look for
- /// the jsonp function name
- /// </summary>
- public string JsonpParameterName { get; set; }
- /// <summary>
- /// Captured name of the Jsonp function that the JSON call
- /// is wrapped in. Set in GetPerRequestFormatter Instance
- /// </summary>
- private string JsonpCallbackFunction;
- public override bool CanWriteType(Type type)
- {
- return true;
- }
- /// <summary>
- /// Override this method to capture the Request object
- /// </summary>
- /// <param name="type"></param>
- /// <param name="request"></param>
- /// <param name="mediaType"></param>
- /// <returns></returns>
- public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
- {
- var formatter = new JsonpFormatter()
- {
- JsonpCallbackFunction = GetJsonCallbackFunction(request)
- };
- // this doesn't work unfortunately
- //formatter.SerializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
- // You have to reapply any JSON.NET default serializer Customizations here
- formatter.SerializerSettings.Converters.Add(new StringEnumConverter());
- formatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
- return formatter;
- }
- public override Task WriteToStreamAsync(Type type, object value,
- Stream stream,
- HttpContent content,
- TransportContext transportContext)
- {
- if (string.IsNullOrEmpty(JsonpCallbackFunction))
- return base.WriteToStreamAsync(type, value, stream, content, transportContext);
- StreamWriter writer = null;
- // write the pre-amble
- try
- {
- writer = new StreamWriter(stream);
- writer.Write(JsonpCallbackFunction + "(");
- writer.Flush();
- }
- catch (Exception ex)
- {
- try
- {
- if (writer != null)
- writer.Dispose();
- }
- catch { }
- var tcs = new TaskCompletionSource<object>();
- tcs.SetException(ex);
- return tcs.Task;
- }
- return base.WriteToStreamAsync(type, value, stream, content, transportContext)
- .ContinueWith(innerTask =>
- {
- if (innerTask.Status == TaskStatus.RanToCompletion)
- {
- writer.Write(")");
- writer.Flush();
- }
- writer.Dispose();
- return innerTask;
- }, TaskContinuationOptions.ExecuteSynchronously)
- .Unwrap();
- }
- /// <summary>
- /// Retrieves the Jsonp Callback function
- /// from the query string
- /// </summary>
- /// <returns></returns>
- private string GetJsonCallbackFunction(HttpRequestMessage request)
- {
- if (request.Method != HttpMethod.Get)
- return null;
- var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
- var queryVal = query[this.JsonpParameterName];
- if (string.IsNullOrEmpty(queryVal))
- return null;
- return queryVal;
- }
- }
- }
برای استفاده از این کد باید تغییر زیر را در متد Application_Start() در فایل Global.asax.cs انجام دهید.
- GlobalConfiguration.Configuration.Formatters.Insert(0, new WebAPI.JsonpFormatter());
کد جی کوئری برای استفاده از Web API:
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
- <script language="javascript" type="text/javascript">
- function GetInformation() {
- var apiServicePath = "http://localhost:5000/api/";
- jQuery.ajax({
- crossDomain: true,
- dataType: "jsonp",
- url: apiServicePath + "test/GetInformation",
- async: false,
- context: document.body
- }).done(function (data) {
- alert("Done");
- });
- };
- </script>
با تشکر.