在处理数据库查询时,大小写不敏感是一个常见的需求。本文将介绍如何在ASP.NET CoreWeb API中使用OWIN中间件来修改OData查询字符串,以实现对数据库查询的大小写不敏感。
为了复现本文中的场景,您需要以下软件组件:
ASP.NET Core 2.0 Web应用程序
最新的Visual Studio 2017(15.5.x)提供了基于.NET Standard 2.0和.NET Core 2.0或.NET Framework 4.6.1创建Web应用程序和Web服务的模板。
Entity Framework Core
Entity FrameworkCore和SQLite的组合非常受欢迎,因为它易于设置,可移植,并且可以用于小型甚至中型网站。
ODataASP.NET Core
目前(截至2018年1月),在ASP.NET Core中使用OData的唯一方式是使用以下NuGet包:
使用Person类作为EF模型,其Name属性是搜索目标。
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
有关设置DbContext和Entity Framework的进一步设置,请参考附带的示例项目。
OData
根据OData版本4.0规范,数据过滤是通过OData函数contains实现的。
http://localhost:51192/odata/Persons?$filter=contains(Name,'dom')
上面的HTTP请求提供了数据库列Name中包含文本"dom"的所有值。但是,除非它们使用tolower OData函数转换为小写,否则不会找到像"Dominik"或"KINGDOM"这样的值。
http://localhost:51192/odata/Persons?$filter=contains(tolower(Name),'dom')
为了更好的可读性,将正则表达式算法封装在自定义的OWIN中间件ODataQueryStringFixer中。
public class ODataQueryStringFixer : IMiddleware
{
private static readonly Regex ReplaceToLowerRegex = new Regex(@"contains\((?\w+),");
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var input = context.Request.QueryString.Value;
var replacement = @"contains(tolower($1),";
context.Request.QueryString = new QueryString(ReplaceToLowerRegex.Replace(input, replacement));
return next(context);
}
}
然后,创建一个用户友好的扩展方法UseODataQueryStringFixer,将中间件锚定在OWIN管道中。
public static class ODataQueryStringFixerExtensions
{
public static IApplicationBuilder UseODataQueryStringFixer(this IApplicationBuilder app)
{
return app.UseMiddleware();
}
}
最后一步是更新Startup类。
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString(nameof(ApplicationDbContext));
services.AddDbContext(optionsAction =>
optionsAction.UseSqlite(connectionString));
services.AddSingleton();
services.AddOData();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
serviceProvider.InitializeDb();
app.UseODataQueryStringFixer();
var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EntitySet("Persons").EntityType
.OrderBy(nameof(Person.Name), nameof(Person.Birthday))
.Filter(nameof(Person.Name));
app.UseMvc(routeBuilder =>
routeBuilder.MapODataServiceRoute("OData", "odata", builder.GetEdmModel()));
}
就是这样。启动应用程序后,OWIN中间件将扩展查询字符串,使用tolower OData函数。