In the last rotten article, Lao Zhou introduced to you Produces Use of features , In this article, Lao Zhou will introduce another feature class :FormatFilterAttribute.
This feature can be regarded as Filter Waistcoat , Except from Attribute Outside class derivation , It's also achieved IFilterFactory Interface . The reason why it is a vest , Because IFilterFactory Interface requires type implementation CreateInstance Method to generate an object instance of the filter . in other words ,FormatFilterAttribute Class does not really do filtering code , Instead, create a FormatFilter Class .
How does this guy work
This feature class can be applied to class ( controller ) And methods ( In the controller Action) On , It allows the API The caller of takes the initiative to choose the format of the returned data . What kind of operation is this ?
If you used to ( I'm talking about the past , Because now many only support JSON Format ) I have worked on an open platform like Weibo API call , May still remember in URL Select return through parameters on XML still JSON. Such as this :
http://what.com/api/getlist?t=xml
http://what.com/api/getlist?t=json
Yes, of course , The premise is that you write API Support the specified format , If the caller specifies jpg, And you wrote API If you don't support it, you will report an error . How format names make ASP.NET Core Identify the to return Content-Type What about ? Don't worry. , Just look down and see .
Let's talk about it first. FormatFilter How to get features API In the format specified by the caller . There are two ways :
- Find a routing rule named “format” Key words of . It's like MVC In routing rules “controller”、"action" Same keyword . If “format” Keyword recognition json, Then return JSON Formatted data ; If you recognize xml Just go back to XML Formatted data .
- From the request URL Found a query string named “format” Field of , If its value is json Said to return to JSON Formatted data ; if xml Just go back to XML Formatted data . For other values , You have to customize the implementation .
It's best to deal with it through routing rules , First, this method is more flexible , Second, do not occupy URL Query string , So as not to URL Too long .
Just now, Lao Zhou said that routing rules can be used “format” Keyword to identify the format , Want to know why , We can see FormatFilter Source code of class (FormatFilter Feature is just a shell , Nothing to look at ).
public virtual string? GetFormat(ActionContext context)
{
if (context.RouteData.Values.TryGetValue("format", out var obj))
{
// null and string.Empty are equivalent for route values.
var routeValue = Convert.ToString(obj, CultureInfo.InvariantCulture);
return string.IsNullOrEmpty(routeValue) ? null : routeValue;
}
var query = context.HttpContext.Request.Query["format"];
if (query.Count > 0)
{
return query.ToString();
}
return null;
}
It starts with RouteData Look in the dictionary to see if it is related to “format” Corresponding value , If there is , Just go back to ; without , I'll find it again URL Query whether there is “format” Field .
As you can see , stay FormatFilter Class , This GetFormat Method is declared as virtual Of , To put it bluntly , You can customize your search method , Maybe you're not looking for someone named “format” Key words of , But is called “type”. You just start FormatFilter Class derivation , And then rewrite GetFormat Method . Finally, write your own new FormatFilter Sign up to MVC Option Filters In the list .
Try it
The test data class used here is Book.
public class Book
{
/// <summary>
/// Number
/// </summary>
public uint ID { get; set; }
/// <summary>
/// Title
/// </summary>
public string Title { get; set; }
/// <summary>
/// author
/// </summary>
public string Author { get; set; }
/// <summary>
/// Time of issue
/// </summary>
public DateTime PublishTime { get; set; }
}
We assume that Book Object represents the basic information of a book .
then , Let's get a controller .
[Route("api/bkstore")]
[ApiController, FormatFilter]
public class BooksController : ControllerBase
{
[HttpGet("list/{format?}")]
public IEnumerable<Book> ListBooks() => new Book[]
{
new() {ID=5112, Title="C Language from entry to wrist cutting ", Author=" Old week ", PublishTime = new(2011,10,12)},
new() {ID=72543, Title=" Heroes in the sewer ", Author=" Old week ", PublishTime= new(2021,4,17)},
new() {ID=28565, Title=" Lunch box era ", Author=" Lao zhang ", PublishTime= new(2022,5,1)},
new() {ID=80251, Title=" A city man with a lot of money and a stupid brain ", Author=" Bald head strength ", PublishTime= new(2017,6,8)}
};
}
Books The controller applies FormatFilter characteristic , Make the operation methods in the whole controller support format Keyword to choose the data format . Called URL The format is as follows :
http://localhost/api/bkstore/list/json
http://localhost/api/bkstore/list/xml
“{format?}” There is a question mark in , Indicates that this routing parameter is optional , You can omit . If omitted ,ASP.NET Core The application will find the first matching item from the list of registered formats as the default format . for example ,MVC In the format list json、xml、audio/wav Equiform , When {format} After the parameter is omitted , The default choice is json.
stay Program.cs Add other codes in the document , Register at API Controller function , To be called AddXmlSerializerFormatters Method , Only in this way can return be supported XML Formatted data .
var builder = WebApplication.CreateBuilder(args);
// add to XML Format support requires calling AddXmlSerializerFormatters Method
builder.Services.AddControllers().AddXmlSerializerFormatters();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//================================================================
var app = builder.Build();
//================================================================
app.UseSwagger();
app.UseSwaggerUI(o =>
{
o.RoutePrefix = "";
o.SwaggerEndpoint("swagger/v1/swagger.json", "swg");
});
app.MapControllers();
app.Run();
In the above code , Called UseSwaggerUI Other methods , Make the project support Web API Test of , In this place, Lao Zhou has modified some default configurations .
app.UseSwaggerUI(o =>
{
o.RoutePrefix = "";
o.SwaggerEndpoint("swagger/v1/swagger.json", "swg");
});
RoutePrefix Property set access Swagger The path of the page , Default to /swagger Next , I change it to an empty string , It means that you can access , Mainly for the convenience of testing . Direct access http://localhost:xxx/ Just OK. Due to the default prefix /swagger Has been removed , therefore , Get a description API Of JSON The access path of the document should be manually set back to the default path /swagger/v1/swagger.json, Otherwise, it will not be found after running API Information .
because Swagger UI The test page of cannot be {format?} Identified as optional parameters , So you should explicitly add xxx/json or xxx/xml.
http://localhost:5228/api/bkstore/list/json
http://localhost:5228/api/bkstore/list/xml
use XML The result returned when formatting :
use JSON The result returned when formatting :
Add a format by yourself
json、xml yes ASP.NET Core Automatically registered format name , We can also add some formats by ourselves .
builder.Services.AddControllers()
.AddXmlSerializerFormatters()
.AddFormatterMappings(mappings =>
{
mappings.SetMediaTypeMappingForFormat("txtj", "text/json");
});
After calling AddControllers、AddXmlSerializerFormatters after , Homeopathic call AddFormatterMappings Method to add a format map . adopt SetMediaTypeMappingForFormat The method is called txtj The format and text/json relation . In this way , Want to make API return Content-Type by text/json The data of , Just visit like this :
http://localhost:5228/api/bkstore/list/txtj
Earlier, Lao Zhou sold a pass :ASP.NET Core How does the program recognize the corresponding format MIME ? This SetMediaTypeMappingForFormat Method call is the answer . It maintains a Key/Value aggregate ( Understand it as a dictionary ),key Is the name of the format ( This can be customized ), Such as xml、json,jpg etc. , Then there will be one MIME With the corresponding . image json --> application/json,xml --> application/xml、abc --> image/png such .
however , If added txt --> text/plain Mapping , Will fail .
builder.Services.AddControllers().AddXmlSerializerFormatters()
.AddFormatterMappings(mappings =>
{
mappings.SetMediaTypeMappingForFormat("txt", "text/plain");
});
The reason is not ASP.NET Core You are not allowed to do this , But the format does not match . Remember what Lao Zhou said in his last hydrology ,text/plain Default by StringOutputFormatter Class to handle , Only the return value string Method of type . And in our example ListBooks The method is to return a Book List of objects , Type mismatch .
therefore , If you want to map txt --> text/plain On , You need to customize one Formatter, Let it be Book The list becomes a string . This guy can try it by himself ( It's better not to customize this too much , Otherwise, there are arrays and classes , It's hard to do , You can consider Book Class ToString Method , It may be easier ), Lao Zhou then uses another example to illustrate , Because this example does not return an array , Only a single instance is returned , You can scan all public attributes with reflection , Then connect it into a string . Yes, of course , This practice has great limitations , There is no way to apply it to all types , Just for demonstration .
First define the data class we need , It's called Goods, It means a commodity ( Because Lao Zhou opened a grocery store , So use Goods class ).
public class Goods
{
/// <summary>
/// goods ID
/// </summary>
public uint ID { get; set; }
/// <summary>
/// Commodity title
/// </summary>
public string Name { get; set; } = "none";
/// <summary>
/// The unit price
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// remarks
/// </summary>
public string Remark { get; set; } = string.Empty;
}
next , Implement custom Formatter class , The function we need here is to splice the public attributes of the object into a string and return it to the client . So we don't need to realize it completely by ourselves IOutputFormatter Interface , Directly from TextOutputFormatter Class derivation is ok . This product is an abstract class , We need to do two things :
In the constructor, add SupportedMediaTypes Add supported MIME type . What formats do you want it to be compatible with , Just say goodbye Add Just go in OK 了 . In this example, Lao Zhou only hopes it supports text/plain Format , So just add this . Then I have to SupportedEncodings Add supported character encodings to the list , Now it's commonly used UTF-8 Just fine , Reduce a lot of trouble .
Realization WriteResponseBodyAsync Method , Convert the object to be processed into a string , And write back to the response flow .
public class MyOutputFormatter : TextOutputFormatter
{
public MyOutputFormatter()
{
/*
* The following two lines must be included
*/
// Add supported MIME type
SupportedMediaTypes.Add("text/plain");
// Add supported character encoding
SupportedEncodings.Add(Encoding.UTF8);
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
// Get the object instance being processed
object obj = context.Object;
// Get the object's Type
Type objtype = context.ObjectType;
if (obj is null || objtype is null)
{
return;
}
// Find out the public properties
var props = objtype.GetProperties(BindingFlags.Public | BindingFlags.Instance);
StringBuilder strbf = new();
// Read it out one by one
foreach (var p in props)
{
strbf.Append($"{p.Name}=");
object val = p.GetValue(obj);
if (!(val is null))
{
strbf.Append(val);
}
strbf.AppendLine();
}
// Write response content
await context.HttpContext.Response.WriteAsync(strbf.ToString());
}
}
stay Program.cs In file , call AddControllers Method , Put what you just defined Formatter Instance added to OutputFormatters In the list .
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(opt =>
{
opt.OutputFormatters.Add(new MyOutputFormatter());
})
.AddXmlSerializerFormatters()
.AddFormatterMappings(mappings =>
{
mappings.SetMediaTypeMappingForFormat("txt", "text/plain");
});
……
Last , Let's go back and add an operation method to the controller class .
[HttpGet("buy/{format?}")]
public Goods BuySomething() => new Goods
{
ID = 93257,
Name = " Women's backpack made of dinosaur skin ",
Price = 58888.03M,
Remark = " Live delivery , No production license is required , No certificate , No need for quality control , No after sales ; No return or exchange , If the goods have quality problems , Please destroy by yourself "
};
Then run the test ( visit http://localhost:xxxx/api/bkstore/buy/txt). Return results :
ID=93257
Name= Women's backpack made of dinosaur skin
Price=58888.03
Remark= Live delivery , No production license is required , No certificate , No need for quality control , No after sales ; No return or exchange , If the goods have quality problems , Please destroy by yourself
【ASP.NET Core】 Set up Web API Format of response data ——FormatFilter More related articles in the feature article
- angular4 and asp.net core 2 web api
angular4 and asp.net core 2 web api This is a study note . angular 5 The official version is almost out , But it's mainly a performance upgrade . In my submission angular 4 It's very suitable for enterprises , It's like .net ...
- View of , Use ASP.NET Core establish Web API, Always for the first time
ASP.NET Core brief introduction ASP.NET Core Is a cross platform high-performance open source framework , Used to generate cloud enabled and connect Internet New applications of . Use ASP.NET Core, You can : Generate Web Applications and services . Object association ...
- Use ASP.NET Core MVC establish Web API—— Content negotiation of response data ( 7、 ... and )
Use ASP.NET Core MVC establish Web API Use ASP.NET Core MVC establish Web API( One ) Use ASP.NET Core MVC establish Web API( Two ) send ...
- 【ASP.NET Core】 Set up Web API The data format of the response ——Produces Characteristics
The first article of spring , Today, Lao Zhou will talk about a very simple topic with all of you : How to set API The data format of the response . Say essence , Is to set the returned content MIME type (Content-Type head ). Yes, of course , We won't use it in HTTP tube ...
- Use angular4 and asp.net core 2 web api Do an exercise ( One )
This is a study note . angular 5 The official version is almost out , But it's mainly a performance upgrade . In my submission angular 4 It's very suitable for enterprises , It's like .net equally . I use it windows 10 Installation tools : git for ...
- Use angular4 and asp.net core 2 web api Do an exercise ( Four )
The first part : http://www.cnblogs.com/cgzl/p/7755801.html The second part : http://www.cnblogs.com/cgzl/p/7763397.html Third ...
- Use angular4 and asp.net core 2 web api Do an exercise ( Two ), This part is all about angular
Last one : http://www.cnblogs.com/cgzl/p/7755801.html complete client.service.ts: import { Injectable } from '@an ...
- be based on ASP.NET Core establish Web API
Use Visual Studio Create project . file -> newly build -> project , Choose to create ASP.NET Core Web Applications . be based on ASP.NET Core 2.0 , choice API, Authentication select ...
- ASP.NET Core Restful Web API Related resources index
GraphQL Use ASP.NET Core Development GraphQL The server -- Preliminary knowledge ( On ) Use ASP.NET Core Development GraphQL The server -- Preliminary knowledge ( Next ) [ video ] Use ASP.NET C ...
- Use ASP.NET Core establish Web API And links sqlserver database
establish Web API https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.0& ...
Random recommendation
- CODEVS1643 Line segments cover 3[ greedy ]
1643 Line segments cover 3 The time limit : 2 s Space restriction : 256000 KB Question level : gold Gold Answer key Title Description Description On a number axis there is n Bar segment , Now choose ...
- analysis ThreadLocal
If you define a single instance of java bean, It has several properties , But one property is not thread safe , for instance HashMap. And it happens that you don't need to share this property in different threads , That is to say, this property has no cross thread meaning . Then I don't recommend it ...
- ThrottleAttribute
/// <summary> /// Decorates any MVC route that needs to have client requests limited by time. ...
- 【CodeForces 489A】SwapSort
topic Description In this problem your goal is to sort an array consisting of n integers in at most n sw ...
- Function.caller
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/caller Nonstandard ...
- Android And TextView Component learning
One . Based on learning 1.findViewById return View class , This class is all View The parent class of the component . 2. Children have more properties and methods than parents , But if the subclass cannot be found, go to the parent class 3.marquee: Huagai , Running lamp effect :orie ...
- shell practice -- Create accounts in batches
#!/bin/bash #By spinestars #-- #cksum5 Bit acquisition method , There may be duplication #pd="user`head -200 /dev/urandom | cksum | h ...
- How to get oracle RAC 11g asm spfile S files
Method 1 : [[email protected] ~]# su - grid [[email protected] ~]$ sqlplus / as sysasm SQL*Plus: Release 11.2.0.3.0 ...
- JavaSE( Ten ) Gather them together Set
Today's article is about what we didn't understand before TreeSet The comparison between the two is very clear , Also understand its underlying implementation . I hope Bo you can give me some advice ! One .Set Interface 1.1.Set Collection Overview Set aggregate : It's like a jar , Programs can put multiple objects in turn “ ...
- GDB debugging qemu-kvm
GDB debugging qemu-kvm The previous blog posts record some kvm Compile, install and use related packages , But I didn't go deep into the code . Only by looking at the relevant principles of the source code can we better understand kvm. but qemu-kvm A lot of code , For me, look directly at the source code harvest ...