C#(Web API)依赖项注入(带Unity)返回类型接口
我正在用ASP.NET构建一个WebApi。现在,我将整个应用程序划分为几个层,其中两层是“接口”和“模型”(每个层都有自己的.dll)。在“models.dll”中,定义了我的所有模型,并在应用程序启动时将它们注入需要的地方。到现在为止,一直都还不错。现在,当我从控件返回值时,我面临一个问题。让我们假设如下:C#(Web API)依赖项注入(带Unity)返回类型接口,c#,asp.net-web-api,interface,controller,datacontractserializer,C#,Asp.net Web Api,Interface,Controller,Datacontractserializer,我正在用ASP.NET构建一个WebApi。现在,我将整个应用程序划分为几个层,其中两层是“接口”和“模型”(每个层都有自己的.dll)。在“models.dll”中,定义了我的所有模型,并在应用程序启动时将它们注入需要的地方。到现在为止,一直都还不错。现在,当我从控件返回值时,我面临一个问题。让我们假设如下: public class TestController : ApiController { IBusinessObject _businessObject; publi
public class TestController : ApiController
{
IBusinessObject _businessObject;
public TestController(IBusinessObject businessObject)
{
this._businessObject= businessObject;
}
[Route("details/object/{id}")]
[HttpGet]
public ISomeObject GetObjectByNr(int id)
{
return this._businessObject.SearchForObject(id);
}
}
现在,当您查看GetObjectByNr时,您可以看到它的返回类型是ISomeObject
(当然,它的返回类型也是。\u businessObject.SearchForObject(id)也是ISomeObject)。ISomeObject的实际实现在ModelLayer内部,但我不想将其包括在我的WebApi项目中,因为它只能通过接口进行通信。现在,当我像这样运行它时,我得到一个错误,它说我应该使用DataContractResolver
(以及一些关于序列化的内容)。我知道我无法序列化接口,但我认为我的应用程序足够聪明,可以在这里找到合适的类来注入(在开始时,我确实解析了所有接口,并且在调用this.\u businessObject.SearchForObject(id)时工作得很好)
调用了正确的类并用正确的值填充,但就在此时返回对象时,我发现了错误)。我一直在研究SO,发现了一些“方法”,例如KnownType(typeof(SomeObject))
属性。但当我试图在TestController内部设置时,它并没有被识别(但即使这样做可行,它也需要对我的实际模型类的引用,我不希望这样)
有没有办法使我的接口可序列化,并返回正确的对象,而不告诉我的控制器ISomeObject的实现是什么
谢谢编辑:
尝试使用您自己的MediaTypeFormatter
。您可以使用sharpSerializer或Json.NET。有关如何执行此操作的信息,请参见:
编辑说明:下面的代码针对的是MVC控制器,而不是WebAPI ApicController
如果您没有绑定到DataContractSerializer
,那么可以使用其他一些方法,比如json序列化。例如,您可以使用Json.NET。最方便的方法是覆盖默认的Json结果行为:
public class JsonNetResult : JsonResult
{
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
Formatting = Formatting.None;
SerializerSettings = new JsonSerializerSettings();
JsonRequestBehavior = JsonRequestBehavior.DenyGet;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet
&& String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType)
? ContentType
: "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
var serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data);
writer.Flush();
}
}
然后在控制器类中重写Json方法:
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
{
return new JsonNetResult
{
ContentType = contentType,
ContentEncoding = contentEncoding,
Data = data
};
}
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonNetResult
{
ContentType = contentType,
ContentEncoding = contentEncoding,
Data = data,
JsonRequestBehavior = behavior
};
}
然后像这样使用它:
public ActionResult GetObjectByNr(int id)
{
return Json(this._businessObject.SearchForObject(id), JsonRequestBehavior.AllowGet);
}
您是否可以发布您得到的确切错误/异常,没有无法序列化接口的内在原因,想想有多少控制器操作返回
IEnumerable
。接口不可序列化。它们只是一个对象实现的契约。也许我的措辞不准确,但是你可以序列化一个实现接口的对象,而不必知道任何关于实现的信息。例外是德语。这就是为什么我没有发布它的原因。它仍然会帮助您吗?但是当客户机需要一个xml作为响应时,这是行不通的?这是行不通的。即使我包含NewtonSoft.JSON,JsonResult也不会被识别,JSON当然不是XML。如果您需要XML,可以使用sharpSerializer()。我的意思是,使用这种方法,我正在失去这种灵活性(现在客户机可以请求XML和json)。所以当我使用intefaces作为返回类型时,控制器没有办法表现“正常”的行为?(所以我必须通过编程来处理每种输出类型)你是对的,在我的回答中,我的目标是MVC控制器,而不是WebAPI ApicController。对不起,弄错了。但是,您可以在以下教程中使用自定义序列化程序: