百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

一文精通.NET Swagger 使用 一文精通设计模式

yuyutoo 2024-10-12 01:50 1 浏览 0 评论

一文精通.NET Swagger 使用

?

在后端开发中,常用 Web API 模式,对外提供 RESTful API 让前端调用.而其中最著名的就是使用 Swagger(俗称:丝袜哥),Swagger 不但提供了非常直观的页面供开发者查看,还能配置注释说明,分组等,还可以直接在浏览器上测试接口,可以说是,现在不用 Swagger 的后端开发者不是个好开发者.本文将针对我在日常工作中使用 Swagger 的一些总结和例子,基本上属于复制代码就能用.

?
  • 本文默认大家都有点基础,至少使用 VS 创建项目这些不用我再多说.
  • 本文的例子使用微软默认的 Web API 模板进行构建,会详细的讲解每一步.并且会将代码上传到 GitHub.
  • 本文会介绍 Swagger 的注释,接口分组,隐藏接口,以及给需要授权的接口添加标识.以及受支持的数据类型的默认值显示.
    • 注释不用说,就是将代码注释显示到页面上.
    • 接口分组可以实现将不同功能的控制器分到不同的组中,便于查看.
    • 隐藏接口则是将不希望对外公开的接口不显示,鉴权接口标识则是在 API 的后边显示一个 ?? 锁图标.
    • 显示默认值则是在某些数据中,比如用户年龄,默认显示 20,前端一看就知道这是个什么数据类型,当然这里的例子不太恰当,反正意思差不多.
  • 最终呈现的效果大概就是如下,接下来就开始使用代码说明这一切.

  • 首先使用 VS 创建一个 Web API 项目,这里我叫他 Swagger.Sample,你也可以叫他其他名字,随你自己.
  • 默认的 AddSwaggerGen 配置代码里什么都没有,所以没有什么特殊的效果.仅仅只能查看接口和调试而已.
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
// 配置Swagger
builder.Services.AddSwaggerGen();
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
  • 由于默认代码里有个天气数据接口,我们并不需要,所以删掉他们,并添加几个 POST,PUT,GET,DELETE 等接口来做例子,所有的接口均返回一个字符串.参数根据不同的接口类型,会声明不同的参数.但是都不会太复杂,大家肯定都能懂.
  • 将默认的控制器改成如下这个样子.
using Microsoft.AspNetCore.Mvc;

// ReSharper disable ClassNeverInstantiated.Global

namespace Swagger.Sample.Controllers;

/// <summary>
/// 第一个控制器
/// </summary>
[ApiController, Route("[controller]/[action]")]
public class FirstController : ControllerBase
{
/// <summary>
/// Hello {name}
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
public string Hello(string name) => $"Hello {name}";

/// <summary>
/// Hello World
/// </summary>
/// <returns></returns>
[HttpGet]
public string HelloWorld() => "Hello World";

/// <summary>
/// PostOne
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
[HttpPost]
public PostParameter PostOne(PostParameter parameter) => parameter;

/// <summary>
/// PutOne
/// </summary>
/// <param name="id"></param>
/// <param name="put"></param>
/// <returns></returns>
[HttpPut("{id}")]
public string PutOne(string id, PutParameter put) => $"update:{id},{put.Gender}";

/// <summary>
/// DeleteOne
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete("{id}")]
public string DeleteOne(string id) => $"delete {id}";
}

/// <summary>
/// Put参数模拟
/// </summary>
public class PutParameter
{
/// <summary>
/// Gender
/// </summary>
public EGender Gender { get; set; }
}

/// <summary>
/// POST参数模拟
/// </summary>
public class PostParameter : PutParameter
{
/// <summary>
/// Name
/// </summary>
public string Name { get; set; } = string.Empty;

/// <summary>
/// Age
/// </summary>
public int Age { get; set; }
}

/// <summary>
/// 性别枚举
/// </summary>
public enum EGender
{
/// <summary>
///
/// </summary>
男,

/// <summary>
///
/// </summary>

}
  • 上边搞了几个例子.启动后会发现按照预期显示页面.但是没有注释也没有上述别的功能.

添加文档注释

  • 要让 Swagger 显示文档注释,首先要对项目添加 XML 文档生成.
  • 打开项目的 xxx.csproj 我这里是 Swagger.Sample.csproj,在 PropertyGroup 节点下添加 GenerateDocumentationFile 为 Trune 如下内容:
 <PropertyGroup>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
  • 这时候启动项目,虽然会生成相应的文件,但是 Swagger 还是无法正常显示注释,其原因就是尚未对 Swaager 进行配置,这里我们先来添加文档注释显示.
  • 打开 Program.cs 文件.若是进行过封装,可能会是其他文件,这里不做探讨,我们全部都在 Program.cs 中进行.
  • 我们将代码改成如下形式
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
// 配置Swagger
builder.Services.AddSwaggerGen(c =>
{
// 填写文档的一些属性,名称,版本和描述信息
c.SwaggerDoc("Swagger.Sample", new()
{
Title = "Swagger.Sample",
Version = "v1",
Description = "Console.WriteLine(\"????\")"
});
// 找到程序运行目录下的所有xml文件
var files = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
foreach (var file in files)
{
// 配置注释文档
c.IncludeXmlComments(file, true);
}
});
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/Swagger.Sample/swagger.json", "Swagger.Sample v1"));
}
app.UseAuthorization();
app.MapControllers();
app.Run();
  • 可见我们在 AddSwaggerGen 和 UseSwaggerUI 中都添加了一些配置,让 Swagger 可以找到对应的 XML 注释文件,这时候再重新运行程序,即可看到注释了.
  • 这里的配置我们可以看到,不管是文档的名称还是 swagger.json 文件路径均是硬编码的,这方面后边的调整中会逐步调整,这里先不用在意.

  • 到这里注释就基本添加完成,原理也懂了.

文档分组

  • 接口文档分组我这里使用了一些特性,配合反射来获取分组信息.所以我们需要先创建一个工具类来帮助我们方便使用反射.
  • 创建一个 Tool 文件夹,用来放一些扩展类.并新建我们的第一个(这个例子里应该也是最后一个)扩展类 AssemblyHelper.cs,并添加如下代码:
using Microsoft.Extensions.DependencyModel;
using System.Reflection;
using System.Runtime.Loader;

namespace Swagger.Sample.Tools;

/// <summary>
/// 程序集帮助类
/// </summary>
// ReSharper disable once UnusedType.Global
public static class AssemblyHelper
{
private static readonly string[] Filters = { "dotnet-", "Microsoft.", "mscorlib", "netstandard", "System", "Windows" };
private static readonly IEnumerable<Assembly>? _allAssemblies;
private static readonly IEnumerable<Type>? _allTypes;

/// <summary>
/// 需要排除的项目
/// </summary>
private static readonly List<string> FilterLibs = new();

/// <summary>
/// 构造函数
/// </summary>
static AssemblyHelper()
{
_allAssemblies = DependencyContext.Default?.GetDefaultAssemblyNames().Where(c => c.Name is not && !Filters.Any(c.Name.StartsWith) && !FilterLibs.Any(c.Name.StartsWith)).Select(Assembly.Load);
_allTypes = _allAssemblies?.SelectMany(c => c.GetTypes());
}

/// <summary>
/// 添加排除项目,该排除项目可能会影响AutoDependenceInjection自动注入,请使用的时候自行测试.
/// </summary>
/// <param name="names"></param>
public static void AddExcludeLibs(params string[] names) => FilterLibs.AddRangeIfNotContains(names);

/// <summary>
/// 根据程序集名字得到程序集
/// </summary>
/// <param name="assemblyNames"></param>
/// <returns></returns>
public static IEnumerable<Assembly> GetAssembliesByName(params string[] assemblyNames) => assemblyNames.Select(o => AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(AppContext.BaseDirectory, $"{o}.dll")));

/// <summary>
/// 查找指定条件的类型
/// </summary>
public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate) => _allTypes!.Where(predicate).ToArray();

/// <summary>
/// 查找所有指定特性标记的类型
/// </summary>
/// <typeparam name="TAttribute"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindTypesByAttribute<TAttribute>() where TAttribute : Attribute => FindTypesByAttribute(typeof(TAttribute));

/// <summary>
/// 查找所有指定特性标记的类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static IEnumerable<Type> FindTypesByAttribute(Type type) => _allTypes!.Where(a => a.IsDefined(type, true)).Distinct().ToArray();

/// <summary>
/// 查找指定条件的类型
/// </summary>
public static IEnumerable<Assembly> FindAllItems(Func<Assembly, bool> predicate) => _allAssemblies!.Where(predicate).ToArray();

/// <summary>
/// 添加不重复的元素
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="this"></param>
/// <param name="values"></param>
private static void AddRangeIfNotContains<T>(this ICollection<T> @this, params T[] values)
{
foreach (var obj in values)
{
if (@this.Contains(obj)) continue;
@this.Add(obj);
}
}
}
  • 写好帮助类后,即可新建一个特性用来承载我们的分组信息.
  • 新建一个文件夹 Attributes 并添加 ApiGroupAttribute.cs,并写入如下代码:
namespace Swagger.Sample.Attributes;

/// <summary>
/// 被此特性标记的控制器可在Swagger文档分组中发挥作用.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
// ReSharper disable once UnusedMember.Global
// ReSharper disable once UnusedType.Global
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class ApiGroupAttribute : Attribute
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="title"></param>
/// <param name="version"></param>
/// <param name="description"></param>
public ApiGroupAttribute(string title, string version, string description = "")
{
Title = title;
Version = version;
Description = description;
Name = $"{title}-{version}";
}

/// <summary>
/// Doc名称,$"{Title}-{Version}"格式
/// </summary>
public string Name { get; }

/// <summary>
/// 标题
/// </summary>
public string Title { get; }

/// <summary>
/// 版本
/// </summary>
public string Version { get; }

/// <summary>
/// 描述
/// </summary>
public string Description { get; }
}
  • 其中各个字段的含义,均有注释.方便理解.这个时候我们准备工作就做好了,可以开始改造 Programe.cs 中的配置了.
  • 首先创建几个局部变量,用来存储一些信息.
// 文档标题
const string Title = "Test"; // 文档标题
const string Version = "v1"; // 版本
const string Name = $"{Title}-{Version}"; // 文档名称
Dictionary<string, string> docsDic = new(); // 用来存储文档分组的信息
Dictionary<string, string> endPointDic = new(); // 存储文档终结点json信息
  • 然后修改 AddSwaggerGen 和 UseSwaggerUI 为如下内容:
  • 为了方便,后期均会展示完整的 Programe.cs 代码
using Swagger.Sample.Attributes;
using Swagger.Sample.Tools;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

// 配置Swagger
const string Title = "Test"; // 文档标题
const string Version = "v1"; // 版本
const string Name = $"{Title}-{Version}"; // 文档名称
Dictionary<string, string> docsDic = new(); // 用来存储文档分组的信息
Dictionary<string, string> endPointDic = new(); // 存储文档终结点json信息
builder.Services.AddSwaggerGen(c =>
{
// 配置默认分组
c.SwaggerDoc(Name, new()
{
Title = Title,
Version = Version,
Description = "Console.WriteLine(\"????\")"
});
// 配置文档注释
var files = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
foreach (var file in files)
{
c.IncludeXmlComments(file, true);
}
// 获取控制器分组信息和配置分组
var controllers = AssemblyHelper.FindTypesByAttribute<ApiGroupAttribute>();
foreach (var ctrl in controllers)
{
var attr = ctrl.GetCustomAttribute<ApiGroupAttribute>();
if (attr is ) continue;
if (docsDic.ContainsKey(attr.Name)) continue;
_ = docsDic.TryAdd(attr.Name, attr.Description);
c.SwaggerDoc(attr.Name, new()
{
Title = attr.Title,
Version = attr.Version,
Description = attr.Description
});
}
c.DocInclusionPredicate((docName, apiDescription) =>
{
//反射拿到值
var actionList = apiDescription.ActionDescriptor.EndpointMetadata.Where(x => x is ApiGroupAttribute).ToList();
if (actionList.Count != 0)
{
return actionList.FirstOrDefault() is ApiGroupAttribute attr && attr.Name == docName;
}
//判断是否包含这个分组
var not = apiDescription.ActionDescriptor.EndpointMetadata.Where(x => x is not ApiGroupAttribute).ToList();
return not.Count != 0 && docName == Name;
});
});
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
// 默认分组
c.SwaggerEndpoint($"/swagger/{Name}/swagger.json", $"{Title} {Version}");
// 配置使用ApiGroupAttribute的分组
var controllers = AssemblyHelper.FindTypesByAttribute<ApiGroupAttribute>();
foreach (var ctrl in controllers)
{
var attr = ctrl.GetCustomAttribute<ApiGroupAttribute>();
if (attr is ) continue;
if (endPointDic.ContainsKey(attr.Name)) continue;
_ = endPointDic.TryAdd(attr.Name, attr.Description);
c.SwaggerEndpoint($"/swagger/{attr.Name}/swagger.json", $"{attr.Title} {attr.Version}");
}
});
}
app.UseAuthorization();
app.MapControllers();
app.Run();
  • 这里分组的逻辑代码就已经完成了,我们再新建 TwoController 和 ThreeController 控制器来演示分组.
/// <summary>
/// TwoController
/// </summary>
[Route("api/[controller]/[action]"), ApiController, ApiGroup("GroupOne", "v1", "第一个分组")]
public class TwoController : ControllerBase
{
/// <summary>
/// TwoHello
/// </summary>
/// <returns></returns>
[HttpGet]
public string TwoHello() => "Hello GroupOne";
}

/// <summary>
/// ThreeController
/// </summary>
[Route("api/[controller]/[action]"), ApiController, ApiGroup("GroupOne", "v1", "第一个分组")]
public class ThreeController : ControllerBase
{
/// <summary>
/// ThreeHello
/// </summary>
/// <returns></returns>
[HttpGet]
public string ThreeHello() => "Hello GroupOne";
}
  • 可以看到我们分组成功后,选择 GroupOne 分组即可看到 Two 和 Three 控制器的 API 了.

为添加了 Authorize 特性的接口添加锁图标

  • Authorize 为.NET 框架自带的一个特性.被他标记的接口,可以表示该接口需要Token校验通过才能访问.我们可以使用 OpenApiSecurityScheme 来为接口添加锁,不过这个方案有个缺点,会把所有的接口均加上锁,其实我们实际开发中有些接口是不需要的,虽然访问可能没有什么问题,但是这会给前端造成一些误解,比如登录接口有个锁.就会让人很懵 ??.为了避免这些不必要的误解.所以就有了这个需求,为只标记了 Authorize 特性的 API 添加锁图标.
  • 在项目里新建一个文件夹 SwaggerFilters,存放我们的自定义的一些针对 Swagger 的 Filters.这里我们先创建第一个 SwaggerAuthorizeFilter.cs,并添加如下代码.
/// <summary>
/// 在Swagger文档中给需要Authorize的接口添加??
/// </summary>
// ReSharper disable once UnusedMember.Global
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class SwaggerAuthorizeFilter : IOperationFilter
{
/// <summary>
/// Apply
/// </summary>
/// <param name="operation"></param>
/// <param name="context"></param>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
// 先筛选出包含Authorize特性的接口
var authAttributes = context.MethodInfo.DeclaringType?.GetCustomAttributes(true)
.Union(context.MethodInfo.GetCustomAttributes(true))
.OfType<AuthorizeAttribute>();
if (!authAttributes!.Any()) return;
// 然后为其添加SecurityScheme
// 由于项目中大部分使用的都是oauth2 Bearer Token认证所以这里默认以这种方式实现.别的方案请自行调整.
operation.Security = new List<OpenApiSecurityRequirement>
{
new()
{
{
new()
{
Reference = new()
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header
},
new List<string>()
}
}
};
operation.Responses.Add("401", new() { Description = "Unauthorized" });
}
}
  • 写好 Fillter 后事情就简单了.在 AddSwaggerGen 方法中添加一行代码即可.
builder.Services.AddSwaggerGen(c =>
{
...
c.DocInclusionPredicate((docName, apiDescription) =>
{
...
});
c.OperationFilter<SwaggerAuthorizeFilter>(); // 为接口添加锁图标
});
  • 接下来在 ThreeController 中新增一个接口来做验证.
/// <summary>
/// ThreeAuthorize
/// </summary>
/// <returns></returns>
[HttpGet, Authorize]
public string ThreeAuthorize() => "Hello Authorize";
  • 重新启动程序,即可发现添加了 Authorize 特性的接口已经加上了锁.

隐藏接口

  • 有些场景下,我们希望某些接口是内部使用,不对外公开.甚至不需要让前端知道.这个时候我们就可以在 Swagger 里隐藏这种接口或者控制器.这样做的目的是为了降低前端工程师产生的误解,同时也可以将过时的接口隐藏起来,避免前端使用错误,虽然过时接口可以使用 Obsolete 特性来标记,但是他还是能在 Swagger 上看见.
  • 为了隐藏接口,我们需要新建一个特性用来标记需要隐藏的接口或者控制器.
  • 在 Attributes 文件夹中添加 HiddenApiAttribute.cs 并添加如下代码.
/// <summary>
/// 被此特性标记的Action或者控制器可在Swagger文档中隐藏.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class HiddenApiAttribute : Attribute { }
  • 同时还需要在 SwaggerFilters 文件夹中添加 SwaggerHiddenApiFilter.cs 来实现被标记接口隐藏.
  • 其原理就是将被 HiddenApiAttribute 标记的接口从 SwaggerDoc 中移除来达到不显示的目的.
/// <summary>
/// 在Swagger文档中隐藏接口
/// </summary>
// ReSharper disable once UnusedMember.Global
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class SwaggerHiddenApiFilter : IDocumentFilter
{
/// <summary>
/// Apply
/// </summary>
/// <param name="swaggerDoc"></param>
/// <param name="context"></param>
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
foreach (var apiDescription in context.ApiDescriptions)
{
#pragma warning disable IDE0048
if (!apiDescription.TryGetMethodInfo(out var method) || !method.ReflectedType!.IsDefined(typeof(HiddenApiAttribute)) && !method.IsDefined(typeof(HiddenApiAttribute)))
#pragma warning restore IDE0048
continue;
var key = $"/{apiDescription.RelativePath}";
if (key.Contains('?'))
{
var index = key.IndexOf("?", StringComparison.Ordinal);
key = key[..index];
}
_ = swaggerDoc.Paths.Remove(key);
}
}
}
  • 该过滤器的使用方法和前边的 SwaggerAuthorizeFilter 一样,只需要一行代码.
builder.Services.AddSwaggerGen(c =>
{
...
c.OperationFilter<SwaggerAuthorizeFilter>(); // 为接口添加锁图标
c.DocumentFilter<SwaggerHiddenApiFilter>(); // 添加隐藏接口过滤
});
  • 我们再在 ThreeController 中创建一个接口来验证该特性是否生效.
/// <summary>
/// ThreeHidden
/// </summary>
/// <returns></returns>
[HttpGet, HiddenApi]
public string ThreeHidden() => "Hello Hidden";
  • 重新启动程序后,我们会发现 ThreeHidden 并未显示在 Swagger 中说明我们成功了.这里就不再截图了.可以下载源码查看效果.
  • 同样该特性可以作用于控制器,这样整个控制器中的接口均不会显示.

为参数添加默认值显示

  • 目前感觉这个功能 Swagger 支持还不够完美,有一些类型的数据无法正常配置,不过后期会越来越完善的.
  • 这里我们也是利用一个.NET 框架自带的特性 DefaultValue 来实现.不过同样需要自己写一个 Filter 才能实现这种功能.
  • 首先我们在 SwaggerFilters 文件夹中新建一个 Filter,名字叫 SwaggerSchemaFilter.cs 并添加如下代码:
/// <summary>
/// 添加默认值显示
/// </summary>
// ReSharper disable once UnusedMember.Global
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class SwaggerSchemaFilter : ISchemaFilter
{
/// <summary>
/// Apply
/// </summary>
/// <param name="schema"></param>
/// <param name="context"></param>
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (schema.Properties is ) return;
foreach (var info in context.Type.GetProperties())
{
// Look for class attributes that have been decorated with "[DefaultAttribute(...)]".
var defaultAttribute = info.GetCustomAttribute<DefaultValueAttribute>();
if (defaultAttribute is ) continue;
foreach (var property in schema.Properties)
{
// Only assign default value to the proper element.
if (ToCamelCase(info.Name) != property.Key) continue;
property.Value.Example = defaultAttribute.Value as IOpenApiAny;
break;
}
}
}

/// <summary>
/// 转成驼峰形式,这里需要注意一下,可能需要按照你自己的字段规范进行自定义转换,不然对不上.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private static string ToCamelCase(string name) => char.ToLowerInvariant(name[0]) + name[1..];
}
  • 其中 ToCamelCase 方法需要注意一下,我们使用默认的驼峰形式来表示 JSON 字段,所以这里若是不一样,需要自己处理一下.
  • 接下来在 Program.cs 中配置 SwaggerSchemaFilter.
builder.Services.AddSwaggerGen(c =>
{
...
c.DocumentFilter<SwaggerHiddenApiFilter>(); // 添加隐藏接口过滤
c.SchemaFilter<SwaggerSchemaFilter>(); // 添加默认值显示
});
  • 这一切都做好了后,现在回到 FirstController.cs 中,将 PostParameter 类调整下,为了直观点,我加了一个新的对象.并调整成如下代码:
/// <summary>
/// POST参数模拟
/// </summary>
public class PostParameter : PutParameter
{
/// <summary>
/// Name
/// </summary>
[DefaultValue("张三")]
public string Name { get; set; } = string.Empty;

/// <summary>
/// Age
/// </summary>
[DefaultValue(20)]
public int Age { get; set; }

/// <summary>
/// 生日
/// </summary>
[DefaultValue(typeof(DateTime), "2023-04-01")]
public DateTime Birthday { get; set; } = DateTime.Now;
}
  • 在上述例子中,我给 Name 字段添加了默认值:张三,Age 添加了默认值 20,新增 Birthday 字段并设置默认值为 23 年愚人节.
  • DefaultValue 特性第一个参数为数据类型,提供了几个默认的重载,若是没有的话,可以使用 typeof 来指定类型,并用字符串的形式设置默认值显示.
  • 做好这一切后,启动程序,来观察默认值是否设置成功.

  • 可以看到这一切均按照我们的预期实现.

  • 到这里我在工作中使用的功能已经介绍完,若是你有其他的玩法,请提供 PR?? 或者告诉我一起研究.

  • 源码已上传至 GitHub: https://github.com/joesdu/Swagger.Sample

  • 以上功能同样在我的库中已经预定义.可以参考EasilyNET.WebCore

  • Nuget 地址: https://www.nuget.org/packages/EasilyNET.WebCore

  • GitHub 地址: https://github.com/EasilyNET/EasilyNET

  • 本文链接: https://github.com/EasilyNET/docs


相关推荐

jQuery VS AngularJS 你更钟爱哪个?

在这一次的Web开发教程中,我会尽力解答有关于jQuery和AngularJS的两个非常常见的问题,即jQuery和AngularJS之间的区别是什么?也就是说jQueryVSAngularJS?...

Jquery实时校验,指定长度的「负小数」,小数位未满末尾补0

在可以输入【负小数】的输入框获取到焦点时,移除千位分隔符,在输入数据时,实时校验输入内容是否正确,失去焦点后,添加千位分隔符格式化数字。同时小数位未满时末尾补0。HTML代码...

如何在pbootCMS前台调用自定义表单?pbootCMS自定义调用代码示例

要在pbootCMS前台调用自定义表单,您需要在后台创建表单并为其添加字段,然后在前台模板文件中添加相关代码,如提交按钮和表单验证代码。您还可以自定义表单数据的存储位置、添加文件上传字段、日期选择器、...

编程技巧:Jquery实时验证,指定长度的「负小数」

为了保障【负小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【负小数】的方法。HTML代码<inputtype="text"class="forc...

一篇文章带你用jquery mobile设计颜色拾取器

【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...

编程技巧:Jquery实时验证,指定长度的「正小数」

为了保障【正小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【正小数】的方法。HTML做成方法<inputtype="text"class="fo...

jquery.validate检查数组全部验证

问题:html中有多个name[],每个参数都要进行验证是否为空,这个时候直接用required:true话,不能全部验证,只要这个数组中有一个有值就可以通过的。解决方法使用addmethod...

Vue进阶(幺叁肆):npm查看包版本信息

第一种方式npmviewjqueryversions这种方式可以查看npm服务器上所有的...

layui中使用lay-verify进行条件校验

一、layui的校验很简单,主要有以下步骤:1.在form表单内加上class="layui-form"2.在提交按钮上加上lay-submit3.在想要校验的标签,加上lay-...

jQuery是什么?如何使用? jquery是什么功能组件

jQuery于2006年1月由JohnResig在BarCampNYC首次发布。它目前由TimmyWilson领导,并由一组开发人员维护。jQuery是一个JavaScript库,它简化了客户...

django框架的表单form的理解和用法-9

表单呈现...

jquery对上传文件的检测判断 jquery实现文件上传

总体思路:在前端使用jquery对上传文件做部分初步的判断,验证通过的文件利用ajaxFileUpload上传到服务器端,并将文件的存储路径保存到数据库。<asp:FileUploadI...

Nodejs之MEAN栈开发(四)-- form验证及图片上传

这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能。开始之前需要源码同学可以先在git上fork:https://github.com/stoneniqiu/R...

大数据开发基础之JAVA jquery 大数据java实战

上一篇我们讲解了JAVAscript的基础知识、特点及基本语法以及组成及基本用途,本期就给大家带来了JAVAweb的第二个知识点jquery,大数据开发基础之JAVAjquery,这是本篇文章的主要...

推荐四个开源的jQuery可视化表单设计器

jquery开源在线表单拖拉设计器formBuilder(推荐)jQueryformBuilder是一个开源的WEB在线html表单设计器,开发人员可以通过拖拉实现一个可视化的表单。支持表单常用控件...

取消回复欢迎 发表评论: