Skip to content

Commit

Permalink
支持原生Bind特性 #6
Browse files Browse the repository at this point in the history
  • Loading branch information
vipwan committed Oct 10, 2023
1 parent 46e06ac commit faf96b1
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 80 deletions.
10 changes: 8 additions & 2 deletions Biwen.QuickApi.DemoWeb/Apis/HelloApi.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Biwen.QuickApi.Attributes;
using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;


Expand All @@ -18,6 +19,11 @@ public class HelloApiRequest : BaseRequest<HelloApiRequest>
[AliasAs("a")]
public string? Alias { get; set; }

[FromQuery]
public string? Q { get; set; }



public HelloApiRequest()
{
RuleFor(x => x.Name).NotNull().Length(2, 36);
Expand Down Expand Up @@ -91,8 +97,8 @@ public override async Task<HelloApiResponse> ExecuteAsync(HelloApiRequest reques
await Task.CompletedTask;
return new HelloApiResponse
{
Message = $"Hello {request.Name}",
Alias = request.Alias
Message = $"Hello {request.Name} {request.Q}",
Alias = request.Alias,
};
}
}
Expand Down
228 changes: 150 additions & 78 deletions Biwen.QuickApi/IReqBinder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Dynamic;
using System.Xml.Linq;

namespace Biwen.QuickApi
{
Expand Down Expand Up @@ -31,111 +33,181 @@ public virtual async Task<T> BindAsync(HttpContext context)
{
//route > header > body(Post) = querystring(Get)
var @default = new T();
var type = typeof(T);
var props = type.GetProperties();
if (props?.Length == 0) return @default;

var requestMethod = context.Request.Method!;
if (requestMethod == HttpMethods.Get)
foreach (var prop in props!)
{
//querystring
if (prop.Name == nameof(BaseRequest<T>.RealValidator)) continue;

var fromQuery = prop.GetCustomAttribute<FromQueryAttribute>();
if (fromQuery != null)
{
var name = fromQuery.Name ?? prop.Name;
var qs = context.Request.Query;
foreach (var item in qs)
if (qs.ContainsKey(name))
{
var prop = GetProperty(item.Key);
if (prop != null)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
prop.SetValue(@default, value);
}
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(qs[name].ToString());
prop.SetValue(@default, value);
continue;
}
}
}
if (requestMethod == HttpMethods.Head)
{
//header
var fromHeader = prop.GetCustomAttribute<FromHeaderAttribute>();
if ((fromHeader != null))
{
var name = fromHeader.Name ?? prop.Name;
var qs = context.Request.Headers;
foreach (var item in qs)
if (qs.ContainsKey(name))
{
var prop = GetProperty(item.Key);
if (prop != null)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
prop.SetValue(@default, item.Value);
}
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(qs[name].ToString());
prop.SetValue(@default, value);
continue;
}
}
}

if (requestMethod == HttpMethods.Post ||
requestMethod == HttpMethods.Put ||
requestMethod == HttpMethods.Options ||
requestMethod == HttpMethods.Patch ||
requestMethod == HttpMethods.Delete)
{
//form
//{
// var qs = context.Request.Form;
// foreach (var item in qs)
// {
// var prop = typeof(T).GetProperties().FirstOrDefault(x => x.Name.Equals(item.Key, StringComparison.OrdinalIgnoreCase));
// if (prop != null)
// {
// //转换
// var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
// prop.SetValue(@default, item.Value);
// }
// }
//}
//body
var fromRoute = prop.GetCustomAttribute<FromRouteAttribute>();
if (fromRoute != null)
{
var type = typeof(T);
if (type == typeof(EmptyRequest))
var name = fromRoute.Name ?? prop.Name;
var qs = context.Request.RouteValues;
if (qs.ContainsKey(name))
{
return @default;
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(qs[name]?.ToString()!);
prop.SetValue(@default, value);
continue;
}
if (type.GetProperties().Length == 0)
}
var fromService = prop.GetCustomAttribute<FromServicesAttribute>();
if (fromService != null)
{
var service = context.RequestServices.GetService(prop.PropertyType);
if (service != null)
{
return @default;
prop.SetValue(@default, service);
continue;
}

if (type.GetProperties().Any(x => x.GetCustomAttribute<AliasAsAttribute>() != null))
}
var fromForm = prop.GetCustomAttribute<FromFormAttribute>();
if (fromForm != null)
{
var name = fromForm.Name ?? prop.Name;
var qs = context.Request.Form;
if (qs.ContainsKey(name))
{
var jsonObject = await context.Request.ReadFromJsonAsync<ExpandoObject>();
if (jsonObject == null)
return @default;
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(qs[name].ToString());
prop.SetValue(@default, value);
continue;
}
}

if (fromQuery != null ||
fromHeader != null ||
fromRoute != null ||
fromService != null ||
fromForm != null)
{
continue;
}
//如果仍然未找到
{
bool isBodySet = false;

var dic = jsonObject as IDictionary<string, object>;
foreach (var item in dic)
var requestMethod = context.Request.Method!;
if (requestMethod == HttpMethods.Get)
{
//querystring
{
var prop = GetProperty(item.Key);
if (prop != null)
var qs = context.Request.Query;
foreach (var item in qs)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString()!);
prop.SetValue(@default, value);
if (prop != null)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
prop.SetValue(@default, value);
break;
}
}
}
return @default;
}
else
if (requestMethod == HttpMethods.Head)
{
@default = await context.Request.ReadFromJsonAsync<T>();
//header
{
var qs = context.Request.Headers;
foreach (var item in qs)
{
if (prop != null)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
prop.SetValue(@default, item.Value);
break;
}
}
}
}
}
}
//route
{
var qs = context.Request.RouteValues;
foreach (var item in qs)
{
var prop = GetProperty(item.Key);
if (prop != null && item.Value != null)

if (requestMethod == HttpMethods.Post ||
requestMethod == HttpMethods.Put ||
requestMethod == HttpMethods.Options ||
requestMethod == HttpMethods.Patch ||
requestMethod == HttpMethods.Delete)
{
//转换
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value!.ToString()!);
prop.SetValue(@default, item.Value);
//form
//{
// var qs = context.Request.Form;
// foreach (var item in qs)
// {
// var prop = typeof(T).GetProperties().FirstOrDefault(x => x.Name.Equals(item.Key, StringComparison.OrdinalIgnoreCase));
// if (prop != null)
// {
// //转换
// var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(item.Value.ToString());
// prop.SetValue(@default, item.Value);
// }
// }
//}
//body
{
var jsonObject = await context.Request.ReadFromJsonAsync<ExpandoObject>();
var alias = prop.GetCustomAttribute<AliasAsAttribute>();
if (alias != null)
{
var dic = (jsonObject as IDictionary<string, object>)!;
if (dic.TryGetValue(alias.Name, out object? value))
{
//转换
var value2 = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(value.ToString()!);
prop.SetValue(@default, value2);
isBodySet = true;
}
}
else
{
var dic = (jsonObject as IDictionary<string, object>)!;
if (dic.TryGetValue(prop.Name, out object? value))
{
//转换
var value2 = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(value.ToString()!);
prop.SetValue(@default, value2);
isBodySet = true;
}
}
}
}
if (isBodySet) continue;
//route
{
var qs = context.Request.RouteValues;
if (qs.ContainsKey(prop.Name))
{
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(qs[prop.Name]?.ToString()!);
prop.SetValue(@default, value);
continue;
}
}
}
}
Expand Down

0 comments on commit faf96b1

Please sign in to comment.