Byr*_*ahl 6 c# content-negotiation nancy
我有一个NancyContext,我需要Response根据请求的正确内容协商者获得一个正文.我想我可以使用Nancy的Negotiator类来添加模型,设置状态和其他东西.但是,我需要返回一个子类型Response.那么,我可以使用什么来构建响应Negotiator?
这是我的方法:
public Response ConvertToHttpResponse(Exception exception, NancyContext context)
{
var negotiator = new Negotiator(context)
.WithStatusCode(HttpStatusCode.BadRequest)
.WithReasonPhrase(exception.Message);
return ???;
}
Run Code Online (Sandbox Code Playgroud)
我个人更喜欢使用南希谈判代表返回"快乐路径"的结果只(即视图/ jsondto收益),然后返回香草南希响应对象可能发生的任何错误.
这样做的一种方法是直接在模块中返回错误,例如:
public class ProductsModule : NancyModule
{
public ProductsModule()
: base("/products")
{
Get["/product/{productid}"] = _ =>
{
var request = this.Bind<ProductRequest>();
var product = ProductRepository.GetById(request.ProductId);
if (product == null)
{
var error = new Response();
error.StatusCode = HttpStatusCode.BadRequest;
error.ReasonPhrase = "Invalid product identifier.";
return error;
}
var user = UserRepository.GetCurrentUser();
if (false == user.CanView(product))
{
var error = new Response();
error.StatusCode = HttpStatusCode.Unauthorized;
error.ReasonPhrase = "User has insufficient privileges.";
return error;
}
var productDto = CreateProductDto(product);
var htmlDto = new {
Product = productDto,
RelatedProducts = GetRelatedProductsDto(product)
};
return Negotiate
.WithAllowedMediaRange(MediaRange.FromString("text/html"))
.WithAllowedMediaRange(MediaRange.FromString("application/json"))
.WithModel(htmlDto) // Model for 'text/html'
.WithMediaRangeModel(
MediaRange.FromString("application/json"),
productDto); // Model for 'application/json';
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可能会变得相当混乱.我首选的方法是在我的Nancy模块引导程序中设置我的错误处理"一次",并让它捕获已知/预期的异常并使用适当的响应对象返回它们.
一个简单的bootrapper配置示例可能是:
public class MyNancyBootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(
TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
// Register the custom exceptions handler.
pipelines.OnError += (ctx, err) => HandleExceptions(err, ctx); ;
}
private static Response HandleExceptions(Exception err, NancyContext ctx)
{
var result = new Response();
result.ReasonPhrase = err.Message;
if (err is NotImplementedException)
{
result.StatusCode = HttpStatusCode.NotImplemented;
}
else if (err is UnauthorizedAccessException)
{
result.StatusCode = HttpStatusCode.Unauthorized;
}
else if (err is ArgumentException)
{
result.StatusCode = HttpStatusCode.BadRequest;
}
else
{
// An unexpected exception occurred!
result.StatusCode = HttpStatusCode.InternalServerError;
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
使用此方法,您可以重构模块,只需抛出相应的异常即可调用正确的响应类型.在这方面,您可以开始为API创建一套很好的标准.一个例子是:
public class ProductsModule : NancyModule
{
public ProductsModule()
: base("/products")
{
Get["/product/{productid}"] = _ =>
{
var request = this.Bind<ProductRequest>();
var product = ProductRepository.GetById(request.ProductId);
if (product == null)
{
throw new ArgumentException(
"Invalid product identifier.");
}
var user = UserRepository.GetCurrentUser();
if (false == user.CanView(product))
{
throw new UnauthorizedAccessException(
"User has insufficient privileges.");
}
var productDto = CreateProductDto(product);
var htmlDto = new {
Product = productDto,
RelatedProducts = GetRelatedProductsDto(product)
};
return Negotiate
.WithAllowedMediaRange(MediaRange.FromString("text/html"))
.WithAllowedMediaRange(MediaRange.FromString("application/json"))
.WithModel(htmlDto) // Model for 'text/html'
.WithMediaRangeModel(
MediaRange.FromString("application/json"),
productDto); // Model for 'application/json';
}
}
}
Run Code Online (Sandbox Code Playgroud)
这对我来说感觉稍微清洁了,现在我在我的模块中引入了一套标准.:)
您可以考虑做的其他事情,在开发过程中特别有用,可以将完整的异常报告附加到错误响应对象的内容结果中.
一个基本的例子是:
result.Contents = responseStream =>
{
string errorBody = string.Format(
@"<html>
<head>
<title>Exception report</title>
</head>
<body>
<h1>{0}</h1>
<p>{1}</p>
</body>
</html>",
ex.Message,
ex.StackTrace);
// convert error to stream and copy to response stream
var byteArray = Encoding.UTF8.GetBytes(errorBody);
using (var errorStream = new MemoryStream(byteArray))
{
errorStream.CopyTo(responseStream);
}
}
Run Code Online (Sandbox Code Playgroud)
同样,这只是一个非常基本的说明性示例,您必须确定它是否适合您的解决方案,然后对其进行扩展.
| 归档时间: |
|
| 查看次数: |
8200 次 |
| 最近记录: |