• 基于 WebAPI 的 API 实现


    本文基于

    • WebAPI 
    • OData (微软发起的一个格式标准,其中一个比较有意思的是可以直接在 Excel 中填入 API 就可以展示了)
    • Swashbuckle.OData(把 API 生成一个测试页面)

    项目结构

     

    代码

    • SwaggerConfig
      1 [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
      2 
      3 namespace ODataWebAPI
      4 {
      5     /// <summary>
      6     /// SwaggerConfig
      7     /// </summary>
      8     public class SwaggerConfig
      9     {
     10         /// <summary>
     11         /// SwaggerConfig Register
     12         /// </summary>
     13         public static void Register()
     14         {
     15             GlobalConfiguration.Configuration.EnableSwagger(c =>
     16             {
     17                 // By default, the service root url is inferred from the request used to access the docs.
     18                 // However, there may be situations (e.g. proxy and load-balanced environments) where this does not
     19                 // resolve correctly. You can workaround this by providing your own code to determine the root URL.
     20                 //
     21                 //c.RootUrl(req => GetRootUrlFromAppConfig());
     22 
     23                 // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
     24                 // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
     25                 // about them, you can use the "Schemes" option as shown below.
     26                 //
     27                 //c.Schemes(new[] { "http", "https" });
     28 
     29                 // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
     30                 // hold additional metadata for an API. Version and title are required but you can also provide
     31                 // additional fields by chaining methods off SingleApiVersion.
     32                 //
     33                 c.SingleApiVersion("v1", "Sample API for Swashbuckle.OData")
     34                     .Contact(contactBuilder => contactBuilder
     35                     .Url("http://localhost:53515/swagger/ui/index#/"));
     36 
     37                 // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
     38                 // In this case, you must provide a lambda that tells Swashbuckle which actions should be
     39                 // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
     40                 // returns an "Info" builder so you can provide additional metadata per API version.
     41                 //
     42                 //c.MultipleApiVersions(
     43                 //    (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
     44                 //    (vc) =>
     45                 //    {
     46                 //        vc.Version("v2", "Swashbuckle Dummy API V2");
     47                 //        vc.Version("v1", "Swashbuckle Dummy API V1");
     48                 //    });
     49 
     50                 // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
     51                 // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
     52                 // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
     53                 // at the document or operation level to indicate which schemes are required for an operation. To do this,
     54                 // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
     55                 // according to your specific authorization implementation
     56                 //
     57                 //c.BasicAuth("basic")
     58                 //    .Description("Basic HTTP Authentication");
     59                 //
     60                 //c.ApiKey("apiKey")
     61                 //    .Description("API Key Authentication")
     62                 //    .Name("apiKey")
     63                 //    .In("header");
     64                 //
     65                 //c.OAuth2("oauth2")
     66                 //    .Description("OAuth2 Implicit Grant")
     67                 //    .Flow("implicit")
     68                 //    .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
     69                 //    //.TokenUrl("https://tempuri.org/token")
     70                 //    .Scopes(scopes =>
     71                 //    {
     72                 //        scopes.Add("read", "Read access to protected resources");
     73                 //        scopes.Add("write", "Write access to protected resources");
     74                 //    });
     75 
     76                 // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
     77                 //c.IgnoreObsoleteActions();
     78 
     79                 // Each operation be assigned one or more tags which are then used by consumers for various reasons.
     80                 // For example, the swagger-ui groups operations according to the first tag of each operation.
     81                 // By default, this will be controller name but you can use the "GroupActionsBy" option to
     82                 // override with any value.
     83                 //
     84                 //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
     85 
     86                 // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
     87                 // the order in which operations are listed. For example, if the default grouping is in place
     88                 // (controller name) and you specify a descending alphabetic sort order, then actions from a
     89                 // ProductsController will be listed before those from a CustomersController. This is typically
     90                 // used to customize the order of groupings in the swagger-ui.
     91                 //
     92                 //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
     93 
     94                 // If you annotate Controllers and API Types with
     95                 // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
     96                 // those comments into the generated docs and UI. You can enable this by providing the path to one or
     97                 // more Xml comment files.
     98                 //
     99                 var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
    100                 var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".XML";
    101                 var commentsFile = Path.Combine(baseDirectory, "App_Data", commentsFileName);
    102                 c.IncludeXmlComments(commentsFile);
    103 
    104                 // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
    105                 // exposed in your API. However, there may be occasions when more control of the output is needed.
    106                 // This is supported through the "MapType" and "SchemaFilter" options:
    107                 //
    108                 // Use the "MapType" option to override the Schema generation for a specific type.
    109                 // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
    110                 // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
    111                 // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
    112                 // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
    113                 // complex Schema, use a Schema filter.
    114                 //
    115                 //c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
    116                 //
    117                 // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
    118                 // specific type, you can wire up one or more Schema filters.
    119                 //
    120                 //c.SchemaFilter<ApplySchemaVendorExtensions>();
    121 
    122                 // Set this flag to omit schema property descriptions for any type properties decorated with the
    123                 // Obsolete attribute 
    124                 //c.IgnoreObsoleteProperties();
    125 
    126                 // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
    127                 // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
    128                 // works well because it prevents the "implementation detail" of type namespaces from leaking into your
    129                 // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
    130                 // need to opt out of this behavior to avoid Schema Id conflicts.
    131                 //
    132                 //c.UseFullTypeNameInSchemaIds();
    133 
    134                 // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
    135                 // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
    136                 // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
    137                 // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
    138                 // 
    139                 //c.DescribeAllEnumsAsStrings();
    140 
    141                 // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
    142                 //
    143                 // Post-modify Operation descriptions once they've been generated by wiring up one or more
    144                 // Operation filters.
    145                 //
    146                 //c.OperationFilter<AddDefaultResponse>();
    147                 //
    148                 // If you've defined an OAuth2 flow as described above, you could use a custom filter
    149                 // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
    150                 // to execute the operation
    151                 //
    152                 //c.OperationFilter<AssignOAuth2SecurityRequirements>();
    153 
    154                 // Post-modify the entire Swagger document by wiring up one or more Document filters.
    155                 // This gives full control to modify the final SwaggerDocument. You should have a good understanding of
    156                 // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
    157                 // before using this option.
    158                 //
    159                 c.DocumentFilter<ApplyResourceDocumentation>();
    160 
    161                 // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
    162                 // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
    163                 // with the same path (sans query string) and HTTP method. You can workaround this by providing a
    164                 // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs 
    165                 //
    166                 //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
    167 
    168                 // Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
    169                 // alternative implementation for ISwaggerProvider with the CustomProvider option.
    170                 //
    171                 c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c).Configure(odataConfig =>
    172                 {
    173                     // Set this flag to include navigation properties in your entity swagger models
    174                     //
    175                     //odataConfig.IncludeNavigationProperties();
    176                 }));
    177             })
    178                 .EnableSwaggerUi(c =>
    179                 {
    180                     // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
    181                     // The file must be included in your project as an "Embedded Resource", and then the resource's
    182                     // "Logical Name" is passed to the method as shown below.
    183                     //
    184                     //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
    185 
    186                     // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
    187                     // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
    188                     // "Logical Name" is passed to the method as shown above.
    189                     //
    190                     //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
    191 
    192                     // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
    193                     // strings as the possible choices. You can use this option to change these to something else,
    194                     // for example 0 and 1.
    195                     //
    196                     //c.BooleanValues(new[] { "0", "1" });
    197 
    198                     // By default, swagger-ui will validate specs against swagger.io's online validator and display the result
    199                     // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
    200                     // feature entirely.
    201                     //c.SetValidatorUrl("http://localhost/validator");
    202                     //c.DisableValidator();
    203 
    204                     // Use this option to control how the Operation listing is displayed.
    205                     // It can be set to "None" (default), "List" (shows operations for each resource),
    206                     // or "Full" (fully expanded: shows operations and their details).
    207                     //
    208                     //c.DocExpansion(DocExpansion.List);
    209 
    210                     // Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
    211                     // It's typically used to instruct Swashbuckle to return your version instead of the default
    212                     // when a request is made for "index.html". As with all custom content, the file must be included
    213                     // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
    214                     // the method as shown below.
    215                     //
    216                     //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
    217 
    218                     // If your API has multiple versions and you've applied the MultipleApiVersions setting
    219                     // as described above, you can also enable a select box in the swagger-ui, that displays
    220                     // a discovery URL for each version. This provides a convenient way for users to browse documentation
    221                     // for different API versions.
    222                     //
    223                     //c.EnableDiscoveryUrlSelector();
    224 
    225                     // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
    226                     // the Swagger 2.0 specification, you can enable UI support as shown below.
    227                     //
    228                     //c.EnableOAuth2Support("test-client-id", "test-realm", "Swagger UI");
    229                 });
    230         }
    231     }
    232 }
    View Code
    • WebApiConfig

     1 public static class WebApiConfig
     2     {
     3         /// <summary>
     4         /// WebApiConfig Register
     5         /// </summary>
     6         /// <param name="config"></param>
     7         public static void Register(HttpConfiguration config)
     8         {
     9             ODataModelBuilder builder = new ODataConventionModelBuilder();
    10             builder.EntitySet<UserModel>("Users");
    11             config.MapODataServiceRoute(
    12                 routeName: "ODataRoute",
    13                 routePrefix: null,
    14                 model: builder.GetEdmModel());
    15         }
    16     }
    View Code
    • UsersController
     1 public class UsersController : ODataController
     2     {
     3         /// <summary>
     4         /// 查询用户
     5         /// </summary>
     6         /// <returns></returns>
     7         [EnableQuery]
     8         public List<UserModel> Get()
     9         {
    10             return new List<UserModel>()
    11             {
    12                 new UserModel { Id = 1, Name = "Zhang San" },
    13                 new UserModel { Id = 2, Name = "Li Si" }
    14             };
    15         }
    16     }
    View Code
    • AesourceDocumentation
     1 public class ApplyResourceDocumentation : IDocumentFilter
     2     {
     3         /// <summary>
     4         /// Apply
     5         /// </summary>
     6         /// <param name="swaggerDoc"></param>
     7         /// <param name="schemaRegistry"></param>
     8         /// <param name="apiExplorer"></param>
     9         public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    10         {
    11             swaggerDoc.tags = new List<Tag>
    12             {
    13                 new Tag { name = "Users", description = "a RESTier resource" }
    14             };
    15         }
    16     }
    View Code
    • UserModelMap

     1 public class UserModelMap : EntityTypeConfiguration<UserModel>
     2     {
     3         /// <summary>
     4         /// UserModelMap
     5         /// </summary>
     6         public UserModelMap()
     7         {
     8             //this.ToTable("dbo.User");
     9             this.HasKey(u => u.Id);
    10 
    11             this.Property(u => u.Name).IsRequired();
    12         }
    13     }
    View Code
    • UserModel

     1 public class UserModel
     2     {
     3         /// <summary>
     4         /// User Id
     5         /// </summary>
     6         public int Id { get; set; }
     7         /// <summary>
     8         /// User Name
     9         /// </summary>
    10         public string Name { get; set; }
    11     }
    View Code
    • EfContext

     1 public class EfContext : DbContext
     2     {
     3         /// <summary>
     4         /// Users
     5         /// </summary>
     6         public DbSet<UserModel> Users { get; set; }
     7 
     8         /// <summary>
     9         /// EfContext ctor
    10         /// </summary>
    11         public EfContext()
    12             : base("name=EfContext")
    13         {
    14         }
    15 
    16         /// <summary>
    17         /// This method is called when the model for a derived context has been initialized, but
    18         ///             before the model has been locked down and used to initialize the context.  The default
    19         ///             implementation of this method does nothing, but it can be overridden in a derived class
    20         ///             such that the model can be further configured before it is locked down.
    21         /// </summary>
    22         /// <remarks>
    23         /// Typically, this method is called only once when the first instance of a derived context
    24         ///             is created.  The model for that context is then cached and is for all further instances of
    25         ///             the context in the app domain.  This caching can be disabled by setting the ModelCaching
    26         ///             property on the given ModelBuidler, but note that this can seriously degrade performance.
    27         ///             More control over caching is provided through use of the DbModelBuilder and DbContextFactory
    28         ///             classes directly.
    29         /// </remarks>
    30         /// <param name="modelBuilder">The builder that defines the model for the context being created. </param>
    31         protected override void OnModelCreating(DbModelBuilder modelBuilder)
    32         {
    33             base.OnModelCreating(modelBuilder);
    34 
    35             modelBuilder.Configurations.Add(new UserModelMap());
    36         }
    37     }
    View Code

    Tips:

    • 53515 是项目设置 Web 选项里的端口号,具体请查询真实的端口号
    • 勾选项目设置 Build 选项里的XML documentation file,因为 Swagger 会用 xml 里的注释作为说明,请把代码中的 /// 注释补全,这样才能生成说明

           

    运行结果

    由于测试直接返回的固定数据,所以,当运行后就可以通过 API 得到结果了,并且可以通过 Swagger 测试页面看到 API 的信息,并可以测试。

    此例中的 API 为

    http://localhost:53515/Users?$orderby=Id desc  (请求的 API)

    http://localhost:53515/swagger/ui/index#/  (Swagger 生成的测试页面)

  • 相关阅读:
    连分数法解佩尔方程特解
    hdu2281&&POJ1320——Pell方程
    Gym
    代入法求递推式
    nodemcu固件的烧录及lua开发
    ESP8266MOD、刷可以使用AT指令的固件、作为客户端向贝壳云端发送固定数据
    Quick Start NodeMCU / ESP8266 12E
    CF388C&&2018EC Final D题——博弈&&水题
    使用cookie登录网盘账号
    Spring的Bean之Bean的基本概念
  • 原文地址:https://www.cnblogs.com/heyixiaoran/p/5715303.html
Copyright © 2020-2023  润新知