การใช้ASP.NET Web API ที่ใหม่กว่าในChromeฉันเห็น XML - ฉันจะเปลี่ยนเป็นขอJSONเพื่อให้สามารถดูได้ในเบราว์เซอร์ได้อย่างไร ฉันเชื่อว่ามันเป็นเพียงส่วนหนึ่งของส่วนหัวของคำขอฉันจะแก้ไขให้ถูกต้องหรือไม่
การใช้ASP.NET Web API ที่ใหม่กว่าในChromeฉันเห็น XML - ฉันจะเปลี่ยนเป็นขอJSONเพื่อให้สามารถดูได้ในเบราว์เซอร์ได้อย่างไร ฉันเชื่อว่ามันเป็นเพียงส่วนหนึ่งของส่วนหัวของคำขอฉันจะแก้ไขให้ถูกต้องหรือไม่
คำตอบ:
ฉันเพิ่งเพิ่มสิ่งต่อไปนี้ในApp_Start / WebApiConfig.cs
ชั้นเรียนในโครงการMVC Web APIของฉัน
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
ทำให้แน่ใจว่าคุณได้ JSON แบบสอบถามมากที่สุด แต่คุณจะได้รับเมื่อคุณส่งXML
text/xml
หากคุณต้องการที่จะมีการตอบสนองContent-Type
เป็นapplication/json
โปรดตรวจสอบคำตอบของทอดด์ด้านล่าง
NameSpace
System.Net.Http.Headers
ใช้
Content-Type
text/html
หากคุณทำสิ่งนี้ในที่WebApiConfig
คุณจะได้รับ JSON โดยค่าเริ่มต้น แต่มันจะยังช่วยให้คุณกลับ XML ถ้าคุณผ่านtext/xml
เป็นAccept
ส่วนหัวของคำขอ
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
}
หากคุณไม่ได้ใช้ประเภทโครงการ MVC ดังนั้นจึงไม่มีคลาสนี้ให้เริ่มด้วยดูคำตอบนี้สำหรับรายละเอียดเกี่ยวกับวิธีรวมเข้าด้วยกัน
application/xml
มีระดับความสำคัญ 0.9 และที่*/*
มีความสำคัญ 0.8 ด้วยการลบapplication/xml
คุณจะลบความสามารถสำหรับ Web API เพื่อส่งคืน XML หากไคลเอ็นต์ร้องขอเฉพาะ เช่นถ้าคุณส่ง "ยอมรับ: application / xml" คุณจะยังคงได้รับ JSON
การใช้ RequestHeaderMapping ทำงานได้ดียิ่งขึ้นเพราะมันตั้งค่าContent-Type = application/json
ในส่วนหัวการตอบสนองซึ่งช่วยให้ Firefox (ด้วย JSONView add-on) เพื่อจัดรูปแบบการตอบสนองเป็น JSON
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
ฉันชอบแนวทางของ Felipe Leusinดีที่สุด - ตรวจสอบให้แน่ใจว่าเบราว์เซอร์รับ JSON โดยไม่กระทบการเจรจาต่อรองเนื้อหาจากลูกค้าที่ต้องการ XML จริง ๆ สิ่งเดียวที่ขาดหายไปสำหรับฉันคือส่วนหัวการตอบสนองยังคงมีประเภทเนื้อหา: text / html เหตุใดจึงเป็นปัญหา เนื่องจากฉันใช้ส่วนขยาย JSON Formatter Chromeซึ่งตรวจสอบประเภทเนื้อหาและฉันไม่ได้รับการจัดรูปแบบที่สวยงามที่ฉันคุ้นเคย ฉันแก้ไขด้วยตัวจัดรูปแบบกำหนดเองแบบง่ายที่ยอมรับการร้องขอ text / html และส่งคืนการตอบกลับของแอปพลิเคชัน / json:
public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
public BrowserJsonFormatter() {
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
this.SerializerSettings.Formatting = Formatting.Indented;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) {
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
ลงทะเบียนเช่นนั้น:
config.Formatters.Add(new BrowserJsonFormatter());
this.SerializerSettings.Formatting = Formatting.Indented;
ถ้าคุณต้องการพิมพ์สวยโดยไม่มีส่วนขยายเบราว์เซอร์
using System.Net.Http.Formatting
และusing Newtonsoft.Json
เคล็ดลับฉบับย่อ MVC4 # 3 - การลบฟอร์แมต XML จาก ASP.Net Web API
ในการGlobal.asax
เพิ่มบรรทัด:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
ชอบมาก:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
ในWebApiConfig.csเพิ่มไปยังจุดสิ้นสุดของฟังก์ชันRegister :
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
ในGlobal.asaxฉันใช้รหัสด้านล่าง URI ของฉันเพื่อรับ JSON คือhttp://www.digantakumar.com/api/values?json=true
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));
}
ดูการเจรจาต่อรองเนื้อหาใน WebAPI โพสต์บล็อกเหล่านี้ ( ตอนที่ 1และส่วนที่ 2 ) มีรายละเอียดที่ยอดเยี่ยมและละเอียดถี่ถ้วนอธิบายวิธีการทำงานของบล็อก
กล่าวโดยย่อคือคุณพูดถูกและจำเป็นต้องตั้งค่าAccept
หรือContent-Type
ขอส่วนหัว ป.ร. Accept: application/json
ให้การดำเนินการของคุณไม่ได้รหัสที่จะกลับมาในรูปแบบที่เฉพาะเจาะจงคุณสามารถตั้งค่า
เนื่องจากคำถามคือเฉพาะ Chrome คุณสามารถรับส่วนขยายบุรุษไปรษณีย์ซึ่งช่วยให้คุณกำหนดประเภทเนื้อหาคำขอ
network.http.accept.default
text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7
text/html,application/xhtml+xml;q=1.0,*/*;q=0.7
เพื่อหลีกเลี่ยงโฮสต์ที่มีบั๊กเช่น Bitbucket จากการให้บริการ JSON เบราว์เซอร์ของคุณโดยไม่ได้ตั้งใจแทน HTML
ทางเลือกหนึ่งที่รวดเร็วคือการใช้ความเชี่ยวชาญ MediaTypeMapping นี่คือตัวอย่างของการใช้ QueryStringMapping ในเหตุการณ์ Application_Start:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
ตอนนี้เมื่อใดก็ตามที่ URL มีการสอบถาม? a = b ในกรณีนี้การตอบสนองของ Json จะปรากฏในเบราว์เซอร์
รหัสนี้ทำให้ json เป็นค่าเริ่มต้นและอนุญาตให้ฉันใช้รูปแบบ XML ได้เช่นกัน xml=true
ฉันเพิ่งจะผนวก
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
ขอบคุณทุกคน!
อย่าใช้เบราว์เซอร์ของคุณเพื่อทดสอบ API ของคุณ
ให้ลองใช้ไคลเอ็นต์ HTTP ที่ให้คุณระบุคำขอเช่น CURL หรือแม้แต่พู้ทำเล่นแทน
ปัญหาเกี่ยวกับปัญหานี้อยู่ในไคลเอนต์ไม่ใช่ใน API API ของเว็บทำงานอย่างถูกต้องตามคำขอของเบราว์เซอร์
คำตอบข้างต้นส่วนใหญ่มีเหตุผลสมบูรณ์แบบ เนื่องจากคุณเห็นข้อมูลที่ถูกจัดรูปแบบในรูปแบบ XML นั่นหมายถึงมีการใช้ตัวจัดรูปแบบ XML ดังนั้นคุณสามารถดูรูปแบบ JSON ได้โดยการลบ XMLFormatter ออกจากพารามิเตอร์ HttpConfiguration เช่น
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.EnableSystemDiagnosticsTracing();
}
เนื่องจาก JSON เป็นรูปแบบเริ่มต้น
ฉันใช้ตัวกรองการกระทำทั่วโลกเพื่อลบAccept: application/xml
เมื่อUser-Agent
ส่วนหัวมี "Chrome":
internal class RemoveXmlForGoogleChromeFilter : IActionFilter
{
public bool AllowMultiple
{
get { return false; }
}
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(
HttpActionContext actionContext,
CancellationToken cancellationToken,
Func<Task<HttpResponseMessage>> continuation)
{
var userAgent = actionContext.Request.Headers.UserAgent.ToString();
if (userAgent.Contains("Chrome"))
{
var acceptHeaders = actionContext.Request.Headers.Accept;
var header =
acceptHeaders.SingleOrDefault(
x => x.MediaType.Contains("application/xml"));
acceptHeaders.Remove(header);
}
return await continuation();
}
}
ดูเหมือนว่าจะทำงาน
ฉันพบว่าแอป Chrome "Advanced REST Client" ยอดเยี่ยมในการทำงานกับบริการ REST คุณสามารถตั้งค่า Content-Type เป็นapplication/json
สิ่งอื่น:
ไคลเอนต์ REST ขั้นสูง
การส่งคืนรูปแบบที่ถูกต้องนั้นทำได้โดยฟอร์แมตเตอร์ชนิดสื่อ ตามที่คนอื่นพูดถึงคุณสามารถทำได้ในWebApiConfig
ชั้นเรียน:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Configure Web API to return JSON
config.Formatters.JsonFormatter
.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
...
}
}
สำหรับข้อมูลเพิ่มเติมตรวจสอบ:
ในกรณีที่การกระทำของคุณส่งคืน XML (ซึ่งเป็นกรณีโดยค่าเริ่มต้น) และคุณต้องการเพียงวิธีการเฉพาะเพื่อส่งคืน JSON จากนั้นคุณสามารถใช้ActionFilterAttribute
และนำไปใช้กับการกระทำที่เฉพาะเจาะจงนั้นได้
คุณลักษณะตัวกรอง:
public class JsonOutputAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
var value = content.Value;
Type targetType = actionExecutedContext.Response.Content.GetType().GetGenericArguments()[0];
var httpResponseMsg = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
RequestMessage = actionExecutedContext.Request,
Content = new ObjectContent(targetType, value, new JsonMediaTypeFormatter(), (string)null)
};
actionExecutedContext.Response = httpResponseMsg;
base.OnActionExecuted(actionExecutedContext);
}
}
นำไปใช้กับการกระทำ:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
โปรดทราบว่าคุณสามารถละเว้นคำAttribute
ในการตกแต่งการดำเนินการและใช้เพียงแทน[JsonOutput]
[JsonOutputAttribute]
config.Formatters.Remove(config.Formatters.XmlFormatter);
ตาม ASP.net WebApi 2 รุ่นล่าสุด
ภายใต้WebApiConfig.cs
สิ่งนี้จะทำงาน
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
มันไม่ชัดเจนสำหรับฉันว่าทำไมความซับซ้อนทั้งหมดนี้ในคำตอบ แน่นอนว่ามีหลายวิธีที่คุณสามารถทำได้ด้วย QueryStrings ส่วนหัวและตัวเลือก ... แต่สิ่งที่ฉันเชื่อว่าเป็นแนวปฏิบัติที่ดีที่สุดนั้นง่าย คุณขอ URL ธรรมดา (เช่น:) http://yourstartup.com/api/cars
และในทางกลับกันคุณจะได้รับ JSON คุณได้รับ JSON พร้อมส่วนหัวการตอบสนองที่เหมาะสม:
Content-Type: application/json
ในการค้นหาคำตอบสำหรับคำถามเดียวกันนี้ฉันพบกระทู้นี้และต้องดำเนินการต่อไปเพราะคำตอบที่ยอมรับนี้ใช้ไม่ได้ผล ฉันพบคำตอบที่ฉันรู้สึกว่าง่ายเกินไปที่จะไม่ใช่คำตอบที่ดีที่สุด:
ตั้งค่าฟอร์แมตเตอร์ WebAPI เริ่มต้น
ฉันจะเพิ่มเคล็ดลับของฉันที่นี่เช่นกัน
WebApiConfig.cs
namespace com.yourstartup
{
using ...;
using System.Net.Http.Formatting;
...
config.Formatters.Clear(); //because there are defaults of XML..
config.Formatters.Add(new JsonMediaTypeFormatter());
}
ฉันมีคำถามว่าค่าเริ่มต้น (อย่างน้อยที่ฉันเห็น) มาจากไหน พวกเขาเป็น. NET เป็นค่าเริ่มต้นหรืออาจสร้างที่อื่น (โดยคนอื่นในโครงการของฉัน) ยังหวังว่านี่จะช่วยได้
นี่คือวิธีการแก้ปัญหาที่คล้ายกับของ jayson.centenoและคำตอบอื่น ๆ System.Net.Http.Formatting
แต่การใช้จากในตัวส่วนขยาย
public static void Register(HttpConfiguration config)
{
// add support for the 'format' query param
// cref: http://blogs.msdn.com/b/hongyes/archive/2012/09/02/support-format-in-asp-net-web-api.aspx
config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
// ... additional configuration
}
โซลูชันนี้มุ่งเน้นไปที่การสนับสนุนรูปแบบ $ สำหรับ OData ในการเผยแพร่ WebApi รุ่นแรก แต่ยังใช้กับการใช้งานที่ไม่ใช่ OData และส่งคืน
Content-Type: application/json; charset=utf-8
ส่วนหัวในการตอบกลับ
ช่วยให้คุณสามารถกลัด&$format=json
หรือ&$format=xml
สิ้นสุด uri ของคุณเมื่อทดสอบกับเบราว์เซอร์ มันไม่รบกวนการทำงานที่คาดหวังอื่น ๆ เมื่อใช้ไคลเอ็นต์ที่ไม่ใช่เบราว์เซอร์ซึ่งคุณสามารถตั้งค่าส่วนหัวของคุณเอง
คุณสามารถใช้ดังต่อไปนี้:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
เพียงเพิ่มโค้ดสองบรรทัดลงในคลาส WebApiConfigของคุณ
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
คุณเพิ่งเปลี่ยนสิ่งApp_Start/WebApiConfig.cs
นี้:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
//Below formatter is used for returning the Json result.
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
//Default route
config.Routes.MapHttpRoute(
name: "ApiControllerOnly",
routeTemplate: "api/{controller}"
);
}
จากMSDN การ สร้างแอปพลิเคชันหน้าเดียวด้วย ASP.NET และ AngularJS (ประมาณ 41 นาที)
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// ... possible routing etc.
// Setup to return json and camelcase it!
var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
formatter.SerializerSettings.ContractResolver =
new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
}
ควรเป็นปัจจุบันฉันลองแล้วใช้งานได้
บางเวลาผ่านไปตั้งแต่คำถามนี้ถูกถาม (และตอบแล้ว) แต่ตัวเลือกอื่นคือแทนที่ส่วนหัว Accept บนเซิร์ฟเวอร์ระหว่างการประมวลผลคำขอโดยใช้ MessageHandler ดังนี้
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
}
return await base.SendAsync(request, cancellationToken);
}
}
ที่ไหน someOtherCondition
สามารถเป็นอะไรก็ได้รวมทั้งชนิดของเบราว์เซอร์อื่น ๆ นี้จะเป็นเงื่อนไขสำหรับกรณีที่มีเพียงบางครั้งเราต้องการแทนที่การเจรจาต่อรองเนื้อหาเริ่มต้น มิฉะนั้นตามคำตอบอื่น ๆ คุณเพียงแค่ลบฟอร์แมตเตอร์ที่ไม่จำเป็นออกจากการกำหนดค่า
คุณจะต้องลงทะเบียนแน่นอน คุณสามารถทำสิ่งนี้ได้ทั่วโลก:
public static void Register(HttpConfiguration config) {
config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
}
หรือบนเส้นทางตามพื้นฐานของเส้นทาง:
config.Routes.MapHttpRoute(
name: "SpecialContentRoute",
routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
constraints: null,
handler: new ForceableContentTypeDelegationHandler()
);
HttpModule
และตั้งแต่นี้เป็นตัวจัดการข้อความมันจะทำงานได้ทั้งบนคำขอและการตอบสนองที่ปลายของท่อเหมือนต์ ดังนั้นคุณสามารถยอมรับการแทนที่ด้วยส่วนหัวที่กำหนดเองได้อย่างง่ายดาย:
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var wasForced = false;
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
wasForced = true;
}
var response = await base.SendAsync(request, cancellationToken);
if (wasForced){
response.Headers.Add("X-ForcedContent", "We overrode your content prefs, sorry");
}
return response;
}
}
นี่เป็นวิธีที่ง่ายที่สุดที่ฉันใช้ในแอปพลิเคชันของฉัน เพิ่มให้ต่ำกว่า 3 บรรทัดของรหัสApp_Start\\WebApiConfig.cs
ในRegister
ฟังก์ชั่น
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
Asp.net web API จะทำให้วัตถุที่ส่งคืนของคุณเป็น JSON โดยอัตโนมัติและapplication/json
จะถูกเพิ่มเข้าไปในส่วนหัวดังนั้นเบราว์เซอร์หรือผู้รับจะเข้าใจว่าคุณกำลังส่งคืนผลลัพธ์ JSON
ด้วยการใช้คำตอบของFelipe Leusinเป็นเวลาหลายปีหลังจากที่มีการอัพเดทไลบรารีหลักและ Json.Net เมื่อเร็ว ๆ นี้ฉันก็พบกับSystem.MissingMethodException
: สื่อสนับสนุน วิธีการแก้ปัญหาในกรณีของฉันหวังว่าเป็นประโยชน์กับคนอื่น ๆ System.Net.Http
ประสบข้อยกเว้นที่ไม่คาดคิดเดียวกันคือการติดตั้ง เห็นได้ชัดว่า NuGet จะลบออกในบางสถานการณ์ หลังจากติดตั้งด้วยตนเองปัญหาได้รับการแก้ไข
ฉันประหลาดใจที่เห็นการตอบกลับจำนวนมากที่ต้องการการเข้ารหัสเพื่อเปลี่ยนเคสการใช้งานครั้งเดียว (GET) ในAPI เดียวแทนที่จะใช้เครื่องมือที่เหมาะสมซึ่งจะต้องติดตั้งครั้งเดียวและสามารถใช้กับAPI ใด ๆ (ของตัวเองหรือของบุคคลที่สาม) และทั้งหมด ใช้กรณี
ดังนั้นคำตอบที่ดีคือ: