如果您想了解HttpPost多次执行async.FromSqlRaw即使它在Web应用程序中只调用一次的知识,那么本篇文章将是您的不二之选。同时我们将深入剖析ASP.NETCore3.1WebApiH
如果您想了解HttpPost 多次执行 async .FromSqlRaw 即使它在 Web 应用程序中只调用一次的知识,那么本篇文章将是您的不二之选。同时我们将深入剖析ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据、asp.net-mvc – [HttpPost] public ActionResult Create(FormCollection collection)VERSUS [HttpPost] public ActionResult Create(Dinner dinner)、Async / Await, Task.Run(async() => await), await Task.Run(()=>), await Task.Run(async() => await) 区别、C# 5.0 async void vs async Task的各个方面,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- HttpPost 多次执行 async .FromSqlRaw 即使它在 Web 应用程序中只调用一次
- ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据
- asp.net-mvc – [HttpPost] public ActionResult Create(FormCollection collection)VERSUS [HttpPost] public ActionResult Create(Dinner dinner)
- Async / Await, Task.Run(async() => await), await Task.Run(()=>), await Task.Run(async() => await) 区别
- C# 5.0 async void vs async Task
HttpPost 多次执行 async .FromSqlRaw 即使它在 Web 应用程序中只调用一次
如何解决HttpPost 多次执行 async .FromSqlRaw 即使它在 Web 应用程序中只调用一次
我有一个 .NET 5/aspnetcore/blazor 服务器 Web 应用程序,应用程序的前端/后端通过应用程序内的 API 层进行通信。
当我在前端调用 API 时,该调用只发出一次(我已经验证了这一点),但在 HttpPost 任务中,dbContext 被查询多次(在我的情况下,每个 API 调用 4 次)。不知道为什么会发生这种情况,希望社区提供任何形式的见解。
这是我的 .razor 文件。如果我在异步 API 请求上设置断点,它只会执行一次。
private async Task FetchData()
{
var result = await Client.GetData(_page,_pageSize);
}
这是我的数据访问代码。如果我在 var response = await _dbContext.Data.FromsqlRaw
上设置断点,它会被击中 4 次。
[HttpPost("/Api/Data/GetData")]
public async Task<IActionResult> GetData([FromQuery] int currentPage,[FromQuery] int currentPageSize)
{
PagedResponse<List<DataDto>> pagedData = new PagedResponse<List<DataDto>>(new List<DataDto>(),currentPage,currentPageSize);
var route = Request.Path.Value;
var filterOut = new PaginationFilter(currentPage,currentPageSize,null,null);
int countResult = 0;
//////////////////////////////////////////////////////////////////////////////////////////
//get paginated set
//////////////////////////////////////////////////////////////////////////////////////////
try
{
sqlParameter[] parameters =
{
new sqlParameter
{
sqlDbType = sqlDbType.Int,Direction = ParameterDirection.Input,ParameterName = "pageNumber",Value = currentPage
},new sqlParameter
{
sqlDbType = sqlDbType.Int,ParameterName = "pageSize",Value = currentPageSize
},Direction = ParameterDirection.Output,ParameterName = "countResult",Value = countResult
}
};
var response = await _dbContext.Data.FromsqlRaw("Execute dbo.sp_GetDataForFilter @pageNumber,@pageSize,@countResult OUTPUT",parameters).AsNoTracking().ToListAsync();
countResult = (int)parameters.Where(x => x.ParameterName == "countResult").FirstOrDefault().Value;
List<DataDto> responseDto = new List<DataDto>();
foreach (var item in response)
{
responseDto.Add(new DataDto(item));
}
//////////////////////////////////////////////////////////////////////////////////////////
//build pagedReponse
//////////////////////////////////////////////////////////////////////////////////////////
pagedData = PaginationHelper.CreatePagedReponse(responseDto,filterOut,countResult,_uriService,route);
return Ok(pagedData);
}
catch (Exception e)
{
//Handle error
}
}
编辑(每个 Henk)---------
这是我的AuthorizationMessageHandler
class AuthorizationMessageHandler : DelegatingHandler
{
private readonly AppStateService _appState;
private readonly ILogger<AuthorizationMessageHandler> _logger;
public AuthorizationMessageHandler(
AppStateService appState,ILogger<AuthorizationMessageHandler> logger)
{
_appState = appState;
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
{
HttpResponseMessage httpResponseMessage;
try
{
if (string.IsNullOrWhiteSpace(_appState?.AuthenticationCookie) == false)
{
request.Headers.Add(HeaderNames.Cookie,_appState.AuthenticationCookie);
}
httpResponseMessage = await base.SendAsync(request,cancellationToken);
httpResponseMessage.EnsureSuccessstatusCode();
}
catch (Exception ex)
{
_logger.LogError(ex,"Failed to run http query {RequestUri}",request.RequestUri);
throw;
}
return httpResponseMessage;
}
}
这里是我在 Startup.cs
private static void InitializeHttp(IServiceCollection services,ServiceConfiguration serviceConfiguration)
{
services.AddTransient<AuthorizationMessageHandler>();
AsyncRetryPolicy<HttpResponseMessage> retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>()
.WaitAndRetryAsync(serviceConfiguration.Http.Retry,_ => TimeSpan.FromMilliseconds(serviceConfiguration.Http.Wait));
AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMilliseconds(serviceConfiguration.Http.Timeout));
// discover all Iapiclient implementations and configure a Refit http client for each.
var apiclientInterfaceType = typeof(Iapiclient);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => apiclientInterfaceType.IsAssignableFrom(t) && t.IsInterface);
foreach (var type in types)
{
// We have to do this nonsense,because there is a bug in AddRefitClient (non-generic version)
// where it does not properly register the client.
MethodInfo method = typeof(Refit.HttpClientFactoryExtensions).getmethods()
.FirstOrDefault(m =>
m.Name.Equals(nameof(Refit.HttpClientFactoryExtensions.AddRefitClient),StringComparison.OrdinalIgnoreCase) &&
m.IsGenericmethod);
MethodInfo generic = method?.MakeGenericmethod(type);
IHttpClientBuilder builder = (IHttpClientBuilder)generic?.Invoke(null,new object[] { services,null });
builder.ConfigureHttpClient(c => c.BaseAddress = new Uri(serviceConfiguration.Application.BaseUrl))
.AddPolicyHandler(retryPolicy)
.AddPolicyHandler(timeoutPolicy)
.AddHttpMessageHandler<AuthorizationMessageHandler>();
}
}
ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据
如何解决ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据
我曾经使用 Controller 而不是 ApiController,今天我尝试使用 ApiController 并发现以下问题。
ASP.NET Core Web Api HttpPost Action 参数无法接收 axios application/json
后传递数据
asp.net 核心 api 代码
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Post(string json)
{
return this.Ok();
}
}
前端
var json = ''{"json_data":"{\\"value\\":\\"hello world\\"}'';
axios.post(''Test'',{"json": json})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
实际请求
Accept:application/json,text/plain,*/*
Accept-Encoding: gzip,deflate,br
Content-Type: application/json;charset=UTF-8
Request Payload :
{"json_data":"{\\"value\\":\\"hello world\\"}
实际动作json参数数据为null
预期接收数据:{"json_data":"{\\"value\\":\\"hello world\\"}
更新
我尝试了下面的代码,我得到 rawValue value = {"json_data":"{\\"value\\":\\"hello world\\"}
但 json value = null
[HttpPost]
public async Task<IActionResult> Post(string json)
{
using (StreamReader reader = new StreamReader(Request.Body,Encoding.UTF8))
{
string rawValue = await reader.ReadToEndAsync();
}
}
解决方法
公共异步任务发布(字符串json)
如果您想从前端使用数据进行 HTTP 请求并将其正确绑定到 string-type ACTION 参数,您可以尝试实现并使用自定义纯文本输入格式化程序。
public class TextPlainInputFormatter : TextInputFormatter
{
public TextPlainInputFormatter()
{
SupportedMediaTypes.Add("text/plain");
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context,Encoding encoding)
{
string data = null;
using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
{
data = await streamReader.ReadToEndAsync();
}
return InputFormatterResult.Success(data);
}
}
配置和添加自定义格式化程序支持
services.AddControllers(opt => opt.InputFormatters.Insert(0,new TextPlainInputFormatter()));
前端代码
const headers = {
''Content-Type'': ''text/plain''
};
var json = ''{"json_data":"{\\"value\\":\\"hello world\\"}'';
axios.post(''test'',json,{ headers: headers })
.then(function (response) {
//...
测试结果
更新:
Demo Source Code Link
我终于用[FromBody]
和System.Text.Json.JsonElement
解决了问题
[HttpPost]
[Route("TestUsingFromBodyAttribute")]
public object TestUsingFromBodyAttribute([FromBody] System.Text.Json.JsonElement content)
{
return content;
}
因为 axios 默认Content-Type: application/x-www-form-urlencoded
需要更新Content-Type'': ''application/json
,否则系统会显示415 unsupported media type
然后它不能使用string
类型或系统会显示400 bad request
因为asp.net核心检查Content-Type'': ''application/json
并使用[FromBody]
会自动转换为json对象(System.Text.Json.JsonElement
),所以不能使用字符串类型。
如果不想编辑axios default Content-Type: application/x-www-form-urlencoded
,必须设置reqeust data is object not string
阅读:
- https://weblog.west-wind.com/posts/2017/sep/14/accepting-raw-request-body-content-in-aspnet-core-api-controllers
早期回答:
现在我用Request.Body而不是Action Parameter来解决这个问题,但是我还是不知道为什么它做不到。
,
[HttpPost]
public async Task<IActionResult> Post()
{
string json = null;
using (StreamReader reader = new StreamReader(Request.Body,Encoding.UTF8))
{
json = await reader.ReadToEndAsync();
}
//..etc
}
您应该使用 FromBodyAttribute 进行正确映射。
asp.net-mvc – [HttpPost] public ActionResult Create(FormCollection collection)VERSUS [HttpPost] public ActionResult Create(Dinner dinner)
第一个依赖于TryUpdateModel来根据传入的表单字段更新模型对象.当传入的表单字段包含无效输入时,ModelState.IsValid将设置为false.
[HttpPost] public ActionResult Create(FormCollection collection) { Dinner dinner = new Dinner(); if (TryUpdateModel(dinner)) { dinnerRepository.Add(dinner); dinnerRepository.Save(); return RedirectToAction("Details",new { id = dinner.DinnerId }); } else return View(dinner); }
第二种方法是利用作为Create action方法arg传递的模型如下:
[HttpPost] public ActionResult Create(Dinner dinner) { if (ModelState.IsValid) { dinnerRepository.Add(dinner); dinnerRepository.Save(); return RedirectToAction("Details",new { id = dinner.DinnerId }); } else return View(dinner); }
哪一个更适合在生产中使用?
解决方法@H_301_23@
如果所有必需的数据都在Request.Form,路由数据或URL查询字符串中,那么您可以使用模型绑定,如第二个示例中所示.
模型绑定器创建您的晚餐对象,并通过匹配属性名称使用请求中的数据填充它.
您可以使用“白名单”,“黑名单”,前缀和标记界面自定义绑定过程.
只要确保你没有无意中绑定值 – 请参阅此link.
模型绑定器创建您的晚餐对象,并通过匹配属性名称使用请求中的数据填充它.
您可以使用“白名单”,“黑名单”,前缀和标记界面自定义绑定过程.
只要确保你没有无意中绑定值 – 请参阅此link.
Async / Await, Task.Run(async() => await), await Task.Run(()=>), await Task.Run(async() => await) 区别
如何解决Async / Await, Task.Run(async() => await), await Task.Run(()=>), await Task.Run(async() => await) 区别
嗨,我是 Xamarin 开发人员
我有一些关于使用异步编程的问题
当我调用 Webservice 时,我通常使用 async/await。
但是,如果它只使用一个线程(UI),那么在 UI 更改时会导致一些问题。
例如,在获取价值之前先处理代码,有时会挂起UI
我阅读了一些关于异步编程的文档或博客。这表明您可以解决使用 Task.RUN 时的问题
但是很难知道我的编程水平.....
这是一些例子,你能解释一下有什么不同吗?
notificationVos = await Task.Run(() => wSSmartConsoleCommon.getScmessage<NotificationVo>());
notificationVos = Task.Run(() => wSSmartConsoleCommon.getScmessage<NotificationVo>());
notificationVos = await wSSmartConsoleCommon.getScmessage<NotificationVo>());
notificationVos = await Task.Run(async() => await wSSmartConsoleCommon.getScmessage<NotificationVo>());
C# 5.0 async void vs async Task
1 private void button1_Click(object sender, EventArgs e)
2 {
3 TestReturnsVoid();//会在UI Thread抛出异常,导致程序崩溃
4 }
5
6 private void button2_Click(object sender, EventArgs e)
7 {
8 TestReturnsTask();//会在另外一个线程抛出异常,类似TheadPool的效果
9 }
10
11 private async void TestReturnsVoid()
12 {
13 await Test();
14 }
15
16 private async Task TestReturnsTask()
17 {
18 await Test();
19 }
20
21 private async Task Test()
22 {
23 throw new NotImplementedException();
24 }
结论
1. async void 仅仅推荐用在UI event handler
2.总是处理事件 : TaskScheduler.UnobservedTaskException
我们今天的关于HttpPost 多次执行 async .FromSqlRaw 即使它在 Web 应用程序中只调用一次的分享已经告一段落,感谢您的关注,如果您想了解更多关于ASP.NET Core 3.1 Web Api HttpPost Action 参数无法接收 axios application/json HttpPost 传递数据、asp.net-mvc – [HttpPost] public ActionResult Create(FormCollection collection)VERSUS [HttpPost] public ActionResult Create(Dinner dinner)、Async / Await, Task.Run(async() => await), await Task.Run(()=>), await Task.Run(async() => await) 区别、C# 5.0 async void vs async Task的相关信息,请在本站查询。
本文标签: