我正在尝试将“Content-Type”标头:“application/x-www-form-urlencoded”发送到最小 api,但出现以下错误:
\n\n\nMicrosoft.AspNetCore.Http.BadHttpRequestException:需要\n支持的 JSON 媒体类型,但得到“application/x-www-form-urlencoded”。
\n
这是端点:
\napp.MapPost("/api/formulario/imovel-web/cadastrar",\n async (LeadRequest request, ILeadService service, ILogService logService, ICorretorMrvRepository corretorMrvRepository) =>\n{\n request.Origem = "imovelweb";\n\n try\n {\n if (string.IsNullOrEmpty(request.Token))\n {\n logService.Error("leads-api", "imovel-web: Acesso n\xc3\xa3o autorizado (Token n\xc3\xa3o encontrado).", Environment.StackTrace, request: request.Serialize());\n\n return Result.ResponseFailed("Acesso n\xc3\xa3o autorizado (Token n\xc3\xa3o encontrado).");\n }\n else\n {\n var idParceiro = await corretorMrvRepository.ObterIdParceiro("imovelweb");\n var origem = string.Empty;\n\n if (idParceiro != Guid.Empty)\n {\n\n var jwt = request.Token;\n var handler = new JwtSecurityTokenHandler();\n var data = handler.ReadJwtToken(request.Token);\n\n var autorizado …Run Code Online (Sandbox Code Playgroud) 能够在集成测试中自定义主机配置有助于避免调用在测试期间根本不应运行的服务。使用标准Startup模型可以轻松实现这一点,CreateHostBuilder覆盖WebApplicationFactory. 我使用“最小 API”方法尝试了很多事情,但无法弄清楚。
使用该模型的完整示例Startup如下:
程序.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
// This is a service that downloads Configuration from the internet, to be used
// as a source for `IConfiguration`, just like any `appsettings.json`.
// I don't want this running during testing
.AddConfigServer();
}
Run Code Online (Sandbox Code Playgroud)
正如您可以想象的那样,AddConfigServer调用外部 Web 服务器来下载我想要在应用程序启动中使用的配置,但我绝对不希望我的集成测试调用此外部 Web 服务器,原因如下:不想依赖外部服务,不想用测试请求来打击我的配置服务器,不想让我的服务器自定义暴露给我的测试,等等。
使用该Startup …
我正在尝试以最小的 API 掌握 swagger 的窍门。我有以下代码:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(setup => setup.SwaggerDoc("v1", new OpenApiInfo()
{
Description = "An api that will change your life for ever",
Title = "Alert Api",
Version = "v1",
Contact = new OpenApiContact()
{
Name = "Grundfos",
Url = new Uri("https://grundfos.com")
}
}));
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//Map endpoints
app.MapGet("/alerts", async () => Results.Ok());
app.MapGet("/profiles", async () => Results.Ok());
Run Code Online (Sandbox Code Playgroud)
这给出了一个看起来像这样的 swagger UI:
我的问题是:如何将端点排序到名为“警报”和“配置文件”的标题下?
我正在探索 .Net 6 中的最小 API,并尝试将自定义授权过滤器应用到端点(通过属性或扩展)。但在我看来,我做错了什么,或者它根本就不是为了以这种方式工作而设计的(如果是这样,那就太可悲了)。除了最小 API 中属性的默认用法之外,在文档中找不到任何内容[Authorize]。
这是过滤器
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//Checking tokens
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试在控制器级别应用它,它工作得很好
[CustomAuthorize]
public class CustomController : ControllerBase
{
//Necessary routing
}
Run Code Online (Sandbox Code Playgroud)
但是如果我切换到 Minimap API 符号并尝试使用属性
app.MapGet("/customEndpoint",
[CustomAuthorize] async ([FromServices] ICustomService customService, Guid id) =>
await customService.GetCustomStuff(id));
Run Code Online (Sandbox Code Playgroud)
甚至是扩展方法
app.MapGet("/customEndpoint",
async ([FromServices] ICustomService customService, Guid id) =>
await customService.GetCustomStuff(id)).WithMetadata(new CustomAuthorizeAttribute());
Run Code Online (Sandbox Code Playgroud)
它就是行不通。过滤器甚至没有被构造。
我错过了什么或做错了什么?提前谢谢
与基于控制器的经典方法相比,ASP.NET Core 6 最小 API 是否应该创建更小的应用程序?
来自微软文档
最小 API 的架构旨在创建具有最小依赖性的 HTTP API。它们非常适合仅在 ASP.NET Core 中包含最少文件、功能和依赖项的微服务和应用程序。
但是,当您在 Visual Studio 中创建两个默认应用程序(一个是最小应用程序和一个基于控制器的应用程序)并发布应用程序时,它们的大小几乎相同。作为依赖于框架的应用程序发布,两者最终都只有 4 MB 左右。
我在这里错过了什么吗?我希望最小的 API 会更小。
我在 .NET 7 中创建了一个最小的 Web API,并且尝试将一些代码提取到单独的程序集中。此代码使用IResult,它是在 .NET 7 中引入的。
如何IResult从常规班级图书馆进行参考?
根据MSDN,该类型应该Microsoft.AspNetCore.Http.Abstractions.dll位于NuGet Microsoft.AspNetCore.App.Refv7.0.3中的程序集中,但那是一个平台组件,不能由程序集直接引用。
为了实现响应缓存,需要做的就是:
.AddResponseCaching()到服务中,[ResponseCache(Duration = 10)]。现在我正在尝试 .NET 6 附带的最小 API,除了自己添加标头之外,我还没有找到其他方法cache-control: public,max-age=10。
有更优雅的方法吗?
我正在尝试注册依赖项,但奇怪的一件事是使用特定处理程序时。例如,采取一个简单的场景,例如:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var handler = new CustomerHandler(); // Compiler error here
app.MapGet("/customers/{id}",
(
[FromQuery(Name = "msg")]string? name,
[FromRoute(Name = "id")]string id) => handler.Get(id, name));
app.Run();
Run Code Online (Sandbox Code Playgroud)
处理程序在其构造函数中接受单个项目。
public class CustomerHandler
{
private readonly IGetCustomerQuery _getCustomerQuery;
public CustomerHandler(IGetCustomerQuery getCustomerQuery)
{
_getCustomerQuery = getCustomerQuery;
}
public async Task<IResult> Get(string id, string name)
{
return Results.Ok(new Customer { Id = id, Name = name });
}
}
Run Code Online (Sandbox Code Playgroud)
我想指定这些依赖项的“正确”方法是什么?我通常会使用BuildServiceProvider()并使用Get<T>()来创建处理程序,但从我所读到的内容来看,这并不理想。所以我想理想的方法是创建这些实例吗?我应该放弃处理程序方法吗?
请注意,这是一个非常简单的示例,但示例的实现
IGetCustomerQuery将采用数据库的配置设置。我想使用传统的 …
我有这个 API,如你所见:
app.MapGet("/api/fund/{fundCode}", ([FromServices] IMediator mediator,string fundCode)
=> mediator.Send(new GetFundsQuery(fundCode)));
Run Code Online (Sandbox Code Playgroud)
我想将其设置fundcode为 API 的可选参数,因此我将其更改为
app.MapGet("/api/fund/{fundCode?}", ([FromServices] IMediator mediator,string fundCode)
=> mediator.Send(new GetFundsQuery(fundCode)));
Run Code Online (Sandbox Code Playgroud)
但它不起作用,当我调用这个地址时
https://localhost:7147/api/fund
Run Code Online (Sandbox Code Playgroud)
我收到 http 404 错误。为什么?
假设我在 Web 应用程序的文件中有以下代码Program.cs,使用最小 API 语法:
app.MapGet("/hello", () => "world");
Run Code Online (Sandbox Code Playgroud)
当使用非最小语法时,我们可以通过用属性装饰控制器来允许匿名访问端点[AllowAnonymous]。
使用最小语法时如何执行相同的操作?
我正在尝试从我的最小 API 中获取结果,该 API 在我的 MVC Web 应用程序的端点中配置,我的 Get 操作配置如下:
endpoints.MapGet(
"HO-CFDZU4/api/Currency/Get",
[PermissionAuthorize(PermissionName.ReadCurrencyDictionary)]
async ([FromServicesAttribute] CurrencyService curency) =>
{
var result = await DataSourceLoader.LoadAsync(curency.Get(), new DataSourceLoadOptions());
return Results.Ok(result);
});
Run Code Online (Sandbox Code Playgroud)
结果我得到了对象的响应,其中属性名称更改为小写,并且它不适合我。我想在相同的情况下获得完全相同的名称,就像我返回表单操作一样。
为了在 MVC 中获得类似的效果,我使用了以下代码:
services
.AddMvc()
.AddFluentValidation(x => x.RegisterValidatorsFromAssembly(AppDomain.CurrentDomain.GetAssemblies().Where(x => x.FullName.Contains("ApplicationCore")).Single()))
.AddMvcLocalization()
.AddMvcOptions(options =>{})
.AddRazorRuntimeCompilation()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
Run Code Online (Sandbox Code Playgroud)
在控制器中使用操作时,它为 Json 设置属性命名策略,但我不知道如何为minimalApi 设置相同的策略。
我尝试过的是设置[JsonPropertyName(name)]它运行良好,但我们有很多课程,我正在寻找更全局的解决方案。
我还尝试像这样全局配置 JsonOptions:
services.Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
Run Code Online (Sandbox Code Playgroud)
但它什么也不做
我正在尝试在我的项目中使用最少的 API。我面临的问题是传统控制器的方式是 swagger 为每个控制器生成一个单独的部分。但我看不到在 Minimal API 中添加这种分离的选项。是否可以使用最少的 API 在 Swagger 中添加不同的部分?
首先,这是一个有效的 POST 映射:
app.MapPost("formulary/uploadSingle/{oldSys}/{newSys}",
async (HttpRequest request, string oldSys, string newSys) =>
{
return await MapUploadSingleFileEndpoint(request, oldSys, newSys);
}).Accepts<IFormFile>("form-data")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest);
Run Code Online (Sandbox Code Playgroud)
MapUploadSingleFileEndpoint 方法使用整个主体来获取文件,如下所示:
using var reader = new StreamReader(request.Body, Encoding.UTF8);
Run Code Online (Sandbox Code Playgroud)
这在 Swagger UI 中完美运行,它显示 2 个参数以及一个文件选择对话框,点击执行返回 200。然后我可以在服务器本地复制文件并随意操作它。请注意,将表单数据更改为任何其他内容都会导致 Swagger 不显示文件部分对话框。
这就是问题所在。我需要一个采用相同参数的端点,只是它需要 2 个文件才能工作。因为我正在阅读整个正文以在前面的方法中获取单个文件,所以我显然不能在这里做同样的事情。即使情况并非如此,IFormFile 类型也会生成一个仅允许单个选择的文件选择器对话框。我尝试将接受更改为IFormFileCollection或,List<IFormFile>但这不起作用,Swagger UI 上没有文件选择器。我决定尝试创建这个自定义请求模型:
public class MultipleFormularyFilesRequest
{
public string OldExternalSystemName { get; set; }
public string NewExternalSystemName { get; set; }
public IFormFile FirstFile { get; set; }
public IFormFile SecondFile { get; set; …Run Code Online (Sandbox Code Playgroud) minimal-apis ×13
c# ×12
asp.net-core ×8
.net-6.0 ×5
.net-core ×3
swagger ×2
.net ×1
asp.net ×1
caching ×1
response ×1
swagger-ui ×1
webapi ×1