[英]Not able to scaffold a controller in ASP.NET 6 Core Web API
[英]ASP.NET Core Web API controller with generic params
我有一个与颤振移动应用程序通信的 ASP.NET Core Web API。
我要添加的功能是通知服务。 问题是我有不止一种通知类型。
这是代码:
public class NotificationSuper
{
public string Title { get; set; }
public string Body { get; set; }
public string Token { get; set; }
public string Type { get; set; }
}
public class UnitNotification :NotificationSuper
{
public String Renter_Key { get; set; }
public String Owner_Key { get; set; }
public String Building_Key { get; set; }
public String Unit_Key { get; set; }
}
public class MaintenanceNotification : UnitNotification
{
public DateTime RequestData { get; set; }
}
等等。
我在其参数中使用超泛型类型为通知编写了一个控制器
[HttpPost]
public async Task<IActionResult> Post([FromBody] NotificationSuper notification)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
bool success = await Notify.Send(notification);
if (success)
{
return Ok();
}
return StatusCode(500);
}
问题是当我从颤振应用程序中检索 JSON 数据时,我只得到NotificationSuper
类的属性,它们是:
public String Renter_Key { get; set; }
public String Owner_Key { get; set; }
public String Building_Key { get; set; }
如果我通过了UnitNotification
或MaintenanceNotification
,我希望有一种灵活的方式来获取每个属性。 我应该有多个控制器,每种类型的通知一个吗?
提前致谢
您可以结合您的UnitNotification
和MaintenanceNotification
它应该看起来像这样
public class CombinedNotification
{
public UnitNotification unitNotification { get; set; }
public MaintenanceNotification maintenanceNotification{ get; set; }
}
然后您的控制器代码应如下所示:
[HttpPost]
public async Task<IActionResult> Post([FromBody] CombinedNotification notification)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
bool success;
if (notification.UnitNotification != null)
{
bool success = await Notify.Send(notification.UnitNotification);
}
if (notification.MaintenanceNotification != null)
{
bool success = await Notify.Send(notification.MaintenanceNotification);
}
if (success)
{
return Ok();
}
return StatusCode(500);
}
重要的是您的帖子数据现在必须从: unitNotification
更改为{"unitNotification": {}}
这里有一个比较灵活的方法,我用的是Polymorphic model binding
,可以参考这个简单的demo:
模型
public abstract class Device
{
public string Kind { get; set; }
public string Name { get; set; }
}
public class Laptop : Device
{
public string CPUIndex { get; set; }
public string Price { get; set; }
}
public class SmartPhone : Device
{
public string ScreenSize { get; set; }
}
模型绑定代码
public class DeviceModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType != typeof(Device))
{
return null;
}
var subclasses = new[] { typeof(Laptop), typeof(SmartPhone), };
var binders = new Dictionary<Type, (ModelMetadata, IModelBinder)>();
foreach (var type in subclasses)
{
var modelMetadata = context.MetadataProvider.GetMetadataForType(type);
binders[type] = (modelMetadata, context.CreateBinder(modelMetadata));
}
return new DeviceModelBinder(binders);
}
}
public class DeviceModelBinder : IModelBinder
{
private Dictionary<Type, (ModelMetadata, IModelBinder)> binders;
public DeviceModelBinder(Dictionary<Type, (ModelMetadata, IModelBinder)> binders)
{
this.binders = binders;
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
var modelKindName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, nameof(Device.Kind));
var modelTypeValue = bindingContext.ValueProvider.GetValue(modelKindName).FirstValue;
IModelBinder modelBinder;
ModelMetadata modelMetadata;
if (modelTypeValue == "Laptop")
{
(modelMetadata, modelBinder) = binders[typeof(Laptop)];
}
else if (modelTypeValue == "SmartPhone")
{
(modelMetadata, modelBinder) = binders[typeof(SmartPhone)];
}
else
{
bindingContext.Result = ModelBindingResult.Failed();
return;
}
var newBindingContext = DefaultModelBindingContext.CreateBindingContext(
bindingContext.ActionContext,
bindingContext.ValueProvider,
modelMetadata,
bindingInfo: null,
bindingContext.ModelName);
await modelBinder.BindModelAsync(newBindingContext);
bindingContext.Result = newBindingContext.Result;
if (newBindingContext.Result.IsModelSet)
{
// Setting the ValidationState ensures properties on derived types are correctly
bindingContext.ValidationState[newBindingContext.Result.Model] = new ValidationStateEntry
{
Metadata = modelMetadata,
};
}
}
}
演示:
注意:这个demo需要来自form的数据,如果需要来自request body的数据,需要修改DeviceModelBinder
中的一些代码,并且父类需要一个属性来指定子类的类名。
请参阅文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.