我正在使用以下消息正文进行REST API调用:
{"Method":{"Token":"0","Value":"0"}}
我从以下机构获得了来自api的400 Bad Request响应:
{“Message”:“请求无效。”,“ModelState”:{“request.Method.Token”:[“无法创建Namespace.ActionMethod类型的实例.Type是一个接口或抽象类,无法实例化。路径'ActionMethod.Token'。“]}}
接收api调用的方法如下所示:
public MethodResponse MakeMethodCall([Required] [FromBody] MethodRequest request)
MethodRequest
具有Method
属性,这是一种抽象类型。
public class MethodRequest
{
public ActionMethod Method { get; set; }
}
public abstract class ActionMethod
{
public string Token { get; set; }
}
public class FirstMethod : ActionMethod
{
public string Value { get; set; }
}
如何调用REST API并让它识别出Method
的类型是FirstMethod
,而不是尝试实例化抽象类型ActionMethod
?
请注意,我将来需要更多ActionMethod
的实现(即。SecondMethod
),因此解决方案需要包含可扩展的ActionMethod
(接口也是细)。
修改
包含enum
以识别 API调用所针对的ActionMethod
的实现也是合理的。
我目前正在使用具有ActionMethodType
枚举以及FirstMethod
和SecondMethod
字段的解决方案。我正在根据ActionMethodType
的值检查这些字段。这有效,但我希望有一个[Required]
字段,我可以通过该字段传递ActionMethod
的任何实现。
答案 0 :(得分:4)
无法完成。框架如何知道为此参数实例化FirstMethod?如果你有另一个ActionMethod子类也有一个Value属性怎么办?现在,框架更难以理解它自己。你可以做一些工作,创建一个自定义格式化程序(http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx)但最终只有一个类包含客户端可以发送的所有可能属性或者具有单独的API端点供客户端调用更容易使用不同的具体类型作为参数。
答案 1 :(得分:2)
如果我理解正确,您可以使用自定义模型绑定器和工厂模式实现此功能。
public class MethodRequestBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
HttpRequestBase request = controllerContext.HttpContext.Request;
//use the request object to make a call to your factory for the
//appropriate ActionMethod subtype you want to create, or however
//else you see fit.
var curActionMethod = MyFactory.Get(request.QueryString);
var boundObj = new MethodRequest()
{
Method = curActionMethod
}
return boundObj;
}
}
在app_start中注册您的模型绑定器:
ModelBinders.Binders.Add(typeof(MethodRequest), new MethodRequestBinder());
现在,只需装饰您的控制器操作方法:
public ActionResult Index([ModelBinder(typeof(MethodRequestBinder))] MethodRequest request)
{
//etc..
}
我以此为出发点:http://www.codeproject.com/Articles/605595/ASP-NET-MVC-Custom-Model-Binder
答案 2 :(得分:-1)
从ActionMethod中删除abstract关键字,或者标记Token属性abstract并在继承的类中覆盖它:
public abstract class ActionMethod
{
public abstract string Token { get; set; }
}
public class FirstMethod : ActionMethod
{
public string Value { get; set; }
public override string Token
{
get;
set;
}
}