这样做可能并且不理想:(一个非常简单的例子!)
[Serializable]
public class MyRecord
{
public string key {get; set;}
public string data {get; set;}
}
public async Task<IHttpActionResult> Get(string SomeKey)
{
if(ExistsInDB(SomeKey))
{
return Ok(SomeRecordFromDB(SomeKey)); //SomeRecord() returns a POCO MyRecord.
}
else
{
//I know I can return NotFound() but not the focus of my Q
return Ok(false); //returns "False"
}
}
有效地证明在返回类型上没有编译时错误检查。这个例子将返回一个JSon序列化的POCO类(JSon在我的接受头上设置)或者它将返回文本&#34; False&#34;这会给客户带来类型检查的负担。
我不会通过设计来做到这一点,但我的团队正在重构asmx / svc中的很多代码并且出现错误。当编译器帮助捕获这些类型时,我喜欢它错误而不是等待模块或单元测试。
回到使用强类型方法签名是正确的方法(避免使用IHttpActionResult和Ok(),NotFound()等辅助工具,还是有类似IHttpActionResult<T>
的东西可以用来确保正在返回正确的类型?
微米。
答案 0 :(得分:3)
首先,最好返回IHttpActionResult
,表示相应的http status
。类似的东西:
public async Task<IHttpActionResult> Get(string SomeKey)
{
if(ExistsInDB(SomeKey))
return Ok(SomeRecordFromDB(SomeKey));
return NotFound();
}
但是如果你真的想要一个强类型的api,你可以做类似的事情:
public async Task<StronglyTypeResponse> Get()
{
return new StronglyTypeResponse();
}
或者,创建一个类型化的响应,并在响应中保留http状态代码等:
public class StronglyTypeResponse
{
}
public class StronglyTypedResult<T> : IHttpActionResult
{
HttpConfiguration _configuration;
T _content;
HttpStatusCode _statusCode;
HttpRequestMessage _request;
public StronglyTypedResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
{
_content = content;
_request = request;
_configuration = configuration;
_statusCode = statusCode;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(_statusCode)
{
Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
RequestMessage = _request,
ReasonPhrase = "some phrase"
};
return Task.FromResult(response);
}
}
然后你可以创建你的方法:
public async Task<StronglyTypedResult<StronglyTypeResponse>> Get()
{
return new StronglyTypedResult<StronglyTypeResponse>(new StronglyTypeResponse(), HttpStatusCode.OK, Request, Configuration);
}
它基本相同:
public class IHttpActionResult<T> : System.Web.Http.IHttpActionResult
{
HttpConfiguration _configuration;
T _content;
HttpStatusCode _statusCode;
HttpRequestMessage _request;
public IHttpActionResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
{
_content = content;
_request = request;
_configuration = configuration;
_statusCode = statusCode;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(_statusCode)
{
Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
RequestMessage = _request,
ReasonPhrase = "some phrase"
};
return Task.FromResult(response);
}
}
现在,您可以使用键入的IHttpActionResult
:
public async Task<IHttpActionResult<YourClass>> Get()
{
var yourclass = new YourClass();
return new IHttpActionResult<YourClass>(yourclass, HttpStatusCode.OK, Request, Configuration);
}
答案 1 :(得分:1)
使用强类型方法签名的问题是,如果请求出现问题,则无法返回“错误”对象,无论是验证错误还是未找到错误。
因此,如果您想使用强类型签名,则必须在返回类型中包含某种“错误”对象引用或显式抛出异常。
使用 HttpActionResult 的好处是您不受限于特定的返回类型。例如,您可以返回 OK(someObject)或 BadRequest(errorObject)。但是,由开发人员正确编写方法并仔细检查没有发生任何事情,如上面提到的示例。
答案 2 :(得分:0)
您可以通过以下方式重构代码:
public class Answer<T>
{
public T result {get;set;}
public bool success {get;set;}
public string exception {get;set;}
}
public async Task<Answer<MyRecord>> Get(string SomeKey)
{
var answer = new Answer<MyRecord>();
try
{
if(ExistsInDB(SomeKey))
{
answer.result = await SomeRecordFromDB(SomeKey);
answer.success = true;
}
}
catch(Exception e)
{
answer.exception = e.Message;
}
return answer;
}
答案 3 :(得分:0)
public class ObjectResult : IHttpActionResult
{
object _value;
HttpRequestMessage _request;
public ObjectResult(object value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
if (_value == null)
return Task.FromResult(_request.CreateResponse(HttpStatusCode.NotFound));
var response = _request.CreateResponse(HttpStatusCode.OK, _value);
return Task.FromResult(response);
}
}
//create your method:
public IHttpActionResult Get()
{
return new ObjectResult(repository.GetAll(), Request);
}