gpt4 book ai didi

asp.net-core - 有没有办法处理 asp.net core odata 错误

转载 作者:行者123 更新时间:2023-12-03 14:10:46 26 4
gpt4 key购买 nike

有没有办法处理 asp.net core odata 错误?

我有一个模型类DimDateAvailable具有一个属性,主键为 int DateId ,然后我调用 /data/DimDateAvailable?$select=test 之类的电话.

其他调用按预期工作并返回我所追求的 - 这是故意调用以生成故障,它失败是因为模型上没有名为 test 的属性。响应按预期返回,如下所示:{"error":{"code":"","message":"The query specified in the URI is not valid. Could not find a property named 'test' on type 'DimDateAvailable'...其次是堆栈跟踪。

env.IsDevelopment() 时,此响应很好。是 true但我不想在未开发时公开堆栈跟踪。

我已经研究过将代码包装在 Controller 的 get 中。 try-catch 中的方法,但我认为有一个 Action 过滤器在结果上运行,因此它永远不会被调用。另一方面,我看不到在哪里注入(inject)任何中间件和/或添加任何过滤器来捕获错误。我怀疑可能有一种方法可以覆盖输出格式化程序以实现我想要的,但我不知道如何。

这是我目前所拥有的:

在 Startup.cs 中:

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<TelemetryDbContext>();
services.AddOData();
services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseMvc(routeBuilder =>
{
routeBuilder.MapODataServiceRoute("odata", "data", GetEdmModel());
routeBuilder.Select().Expand().Filter().OrderBy().MaxTop(null).Count();

// insert special bits for e.g. custom MLE here
routeBuilder.EnableDependencyInjection();
});
}

private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<DimDateAvailable>("DimDateAvailable");
return builder.GetEdmModel();
}

在 TelemetryDbContext.cs 中:
public virtual DbSet<DimDateAvailable> DimDateAvailable { get; set; }

在 DimDateAvailable.cs
public class DimDateAvailable
{
[Key]
public int DateId { get; set; }
}

我的 Controller :
public class DimDateAvailableController : ODataController
{
private readonly TelemetryDbContext data;

public DimDateAvailableController(TelemetryDbContext data)
{
this.data = data;
}

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Supported, PageSize = 2000)]
public IActionResult Get()
{
return Ok(this.data.DimDateAvailable.AsQueryable());
}
}

这是一个带有 Microsoft.AspNetCoreOData v7.0.1 和 EntityFramework 6.2.0 包的 asp.net core 2 Web 应用程序。

最佳答案

调查 Ihar 的建议让我陷入了困境,我最终插入了 ODataOutputFormatter进入 MVC 选项以拦截 ODataPayloadKind.Error响应并重新格式化它们。
有趣的是,context.Features持有 IExceptionHandlerFeature 的实例在 app.UseExceptionHandler()但不在 ODataOutputFormatter .正是这种缺失促使我首先提出这个问题,但通过翻译 context.Object 得到了解决。在 ODataOutputFormatter这也是我在 OData 源中看到的。我不知道下面的更改是否是 asp.net 核心或使用 AspNetCoreOData 包时的良好做法,但它们现在可以满足我的要求。
对 Startup.cs 的更改

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<TelemetryDbContext>();
services.AddOData();
services.AddMvc(options =>
{
options.OutputFormatters.Insert(0, new CustomODataOutputFormatter(this.Environment.IsDevelopment()));
});
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

// Added this to catch errors in my own code and return them to the client as ODataErrors
app.UseExceptionHandler(appBuilder =>
{
appBuilder.Use(async (context, next) =>
{
var error = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
if (error?.Error != null)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";

var response = error.Error.CreateODataError(!env.IsDevelopment());
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
}

// when no error, do next.
else await next();
});
});

app.UseMvc(routeBuilder =>
{
routeBuilder.MapODataServiceRoute("odata", "data", GetEdmModel());
routeBuilder.Select().Expand().Filter().OrderBy().MaxTop(null).Count();

// insert special bits for e.g. custom MLE here
routeBuilder.EnableDependencyInjection();
});
}
新类 CustomODataOutputFormatter.cs 和 CommonExtensions.cs
public class CustomODataOutputFormatter : ODataOutputFormatter
{
private readonly JsonSerializer serializer;
private readonly bool isDevelopment;

public CustomODataOutputFormatter(bool isDevelopment)
: base(new[] { ODataPayloadKind.Error })
{
this.serializer = new JsonSerializer { ContractResolver = new CamelCasePropertyNamesContractResolver() };
this.isDevelopment = isDevelopment;

this.SupportedMediaTypes.Add("application/json");
this.SupportedEncodings.Add(new UTF8Encoding());
}

public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
if (!(context.Object is SerializableError serializableError))
{
return base.WriteResponseBodyAsync(context, selectedEncoding);
}

var error = serializableError.CreateODataError(this.isDevelopment);
using (var writer = new StreamWriter(context.HttpContext.Response.Body))
{
this.serializer.Serialize(writer, error);
return writer.FlushAsync();
}
}
}

public static class CommonExtensions
{
public const string DefaultODataErrorMessage = "A server error occurred.";

public static ODataError CreateODataError(this SerializableError serializableError, bool isDevelopment)
{
// ReSharper disable once InvokeAsExtensionMethod
var convertedError = SerializableErrorExtensions.CreateODataError(serializableError);
var error = new ODataError();
if (isDevelopment)
{
error = convertedError;
}
else
{
// Sanitise the exposed data when in release mode.
// We do not want to give the public access to stack traces, etc!
error.Message = DefaultODataErrorMessage;
error.Details = new[] { new ODataErrorDetail { Message = convertedError.Message } };
}

return error;
}

public static ODataError CreateODataError(this Exception ex, bool isDevelopment)
{
var error = new ODataError();

if (isDevelopment)
{
error.Message = ex.Message;
error.InnerError = new ODataInnerError(ex);
}
else
{
error.Message = DefaultODataErrorMessage;
error.Details = new[] { new ODataErrorDetail { Message = ex.Message } };
}

return error;
}
}
Controller 的变化:
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Supported, PageSize = 2000)]
public IQueryable<DimDateAvailable> Get()
{
return this.data.DimDateAvailable.AsQueryable();
}

关于asp.net-core - 有没有办法处理 asp.net core odata 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51491011/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com