admin管理员组文章数量:1291047
I have a simple viewmodel,
public class AuthenticateViewModel
{
[Required]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
There is a action method with GET and POST
[HttpGet]
[AllowAnonymous]
public IActionResult Authenticate()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Authenticate(AuthenticateViewModel model)
{
if (!ModelState.IsValid)
{
ViewBag.ErrorMessage = "Validation failed";
return View(model);
}
// Do some logic operation
}
I have simple view that displays two text boxes for AuthenticateViewModel and a submit button. The form is posted back to server using Ajax post.
var formData = $("#form-submit").serialize();
$.ajax({
url: targetUrl,
type: "POST",
data: formData,
success: function (response, textStatus, xhr) {
// Do something here
},
error: function (xhr, ajaxOptions, thrownError) {
// Handle error
}
});
So far everything is cool, The form is posting data back to server successfully and my functionality was working perfectly. Later we introduced a middleware, which will read the request payload and logs some information based on the input, which is happening before control reaches to controller action method. You consider it as a RequestMiddleware, sample code given below.
public async Task Invoke(HttpContext httpContext, IRequestLogBuilder requestLogBuilder)
{
var requestPath = httpContext.Request.Path.Value;
var request = httpContext.Request;
if (requestPath != null && ExcludeLogging(requestPath))
{
await _next(httpContext); // Skip logging
return;
}
var originalBodyStream = httpContext.Response.Body;
using (var responseBody = new MemoryStream())
{
try
{
request.EnableRewind();
// use request payload to read some data and log information logic
await _next(httpContext);
// Log some information from response
}
catch (Exception ex)
{
// Handle error scenario
}
}
}
After introducing this middleware on the code, my form started behaving wired. The form works fine for 'x' number of submits and receives response successfully. After that it starts giving me ModelState validation failed messages on the View. The very next form submit is working as expected and it runs successfully. I am unable to identify the root cause about this ModelState validation failure.
After some investigation I found that the model is not populated with the data that was posted by Ajax POST. But I am unable to find out when and where this failure is happening with my form. I have no clue why the default ModelBinding is failed, this behavior is intermittent.
Any help is appreciated.
Thanks.
I have a simple viewmodel,
public class AuthenticateViewModel
{
[Required]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
There is a action method with GET and POST
[HttpGet]
[AllowAnonymous]
public IActionResult Authenticate()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Authenticate(AuthenticateViewModel model)
{
if (!ModelState.IsValid)
{
ViewBag.ErrorMessage = "Validation failed";
return View(model);
}
// Do some logic operation
}
I have simple view that displays two text boxes for AuthenticateViewModel and a submit button. The form is posted back to server using Ajax post.
var formData = $("#form-submit").serialize();
$.ajax({
url: targetUrl,
type: "POST",
data: formData,
success: function (response, textStatus, xhr) {
// Do something here
},
error: function (xhr, ajaxOptions, thrownError) {
// Handle error
}
});
So far everything is cool, The form is posting data back to server successfully and my functionality was working perfectly. Later we introduced a middleware, which will read the request payload and logs some information based on the input, which is happening before control reaches to controller action method. You consider it as a RequestMiddleware, sample code given below.
public async Task Invoke(HttpContext httpContext, IRequestLogBuilder requestLogBuilder)
{
var requestPath = httpContext.Request.Path.Value;
var request = httpContext.Request;
if (requestPath != null && ExcludeLogging(requestPath))
{
await _next(httpContext); // Skip logging
return;
}
var originalBodyStream = httpContext.Response.Body;
using (var responseBody = new MemoryStream())
{
try
{
request.EnableRewind();
// use request payload to read some data and log information logic
await _next(httpContext);
// Log some information from response
}
catch (Exception ex)
{
// Handle error scenario
}
}
}
After introducing this middleware on the code, my form started behaving wired. The form works fine for 'x' number of submits and receives response successfully. After that it starts giving me ModelState validation failed messages on the View. The very next form submit is working as expected and it runs successfully. I am unable to identify the root cause about this ModelState validation failure.
After some investigation I found that the model is not populated with the data that was posted by Ajax POST. But I am unable to find out when and where this failure is happening with my form. I have no clue why the default ModelBinding is failed, this behavior is intermittent.
Any help is appreciated.
Thanks.
Share Improve this question edited Feb 14 at 10:23 Tarak Venkat asked Feb 13 at 15:34 Tarak VenkatTarak Venkat 113 bronze badges 2- How is your JavaScript formData variable created? What is it's scope? Is it recreated for every AJAX operation or is it reused/overwritten? Could it be getting extra properties, potentially with duplicate names that is confusing either the JavaScript AJAX library or the pipeline? – Jeff Zola Commented Feb 13 at 17:41
- @JeffZola Added javascript variable formData on the sample code. I am sure, there is no issue with javascript variable formData, I am seeing a log that AJAX post sending data to the server. It works well but once in "n" no.of times it failed with ModelState validation and even I can see HttpContext.Request.Body has data sent by AJAX POST but data on the model is null. So, ModelState validation failed because it failed to bind data to the Model. – Tarak Venkat Commented Feb 14 at 10:28
1 Answer
Reset to default 0Change your middleware like below can fix the issue.
Here is the test result
RequestLoggingMiddleware.cs
namespace _79436884
{
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var originalBodyStream = httpContext.Response.Body;
try
{
httpContext.Request.EnableBuffering();
var requestBody = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
httpContext.Request.Body.Position = 0; // Key fix: reset stream position
using (var responseBody = new MemoryStream())
{
httpContext.Response.Body = responseBody;
await _next(httpContext);
responseBody.Position = 0;
var responseContent = await new StreamReader(responseBody).ReadToEndAsync();
responseBody.Position = 0;
await responseBody.CopyToAsync(originalBodyStream);
}
}
finally
{
httpContext.Response.Body = originalBodyStream;
}
}
}
}
Here is my detailed steps.
1. HomeController.cs
using _79436884.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace _79436884.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[HttpGet]
[AllowAnonymous]
public IActionResult Authenticate()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Authenticate(AuthenticateViewModel model)
{
if (!ModelState.IsValid)
{
ViewBag.ErrorMessage = "Validation failed";
return View(model);
}
await Task.Delay(100);
return Json(new { success = true });
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
2. AuthenticateViewModel.cs
using System.ComponentModel.DataAnnotations;
namespace _79436884.Models
{
public class AuthenticateViewModel
{
[Required]
public string? Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string? Password { get; set; }
}
}
3. Register the middleware.
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<RequestLoggingMiddleware>();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Authenticate}/{id?}");
app.Run();
4. Authenticate.cshtml
@model _79436884.Models.AuthenticateViewModel
<h2>Login</h2>
<form id="form-submit" asp-action="Authenticate" method="post">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" type="password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="result" class="mt-3"></div>
@section Scripts {
<script>
$(function () {
$('#form-submit').submit(function (e) {
e.preventDefault();
var formData = $(this).serialize();
$.ajax({
url: $(this).attr('action'),
type: "POST",
data: formData,
success: function (response) {
$('#result').html('<div class="alert alert-success">Success!</div>');
},
error: function (xhr) {
var errorMessage = xhr.responseJSON?.errorMessage || "Validation failed";
$('#result').html(`<div class="alert alert-danger">${errorMessage}</div>`);
}
});
});
});
</script>
}
本文标签: cModelstate validation failed unexpectedly even with proper data passed from viewStack Overflow
版权声明:本文标题:c# - Modelstate validation failed unexpectedly even with proper data passed from view - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741520572a2383157.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论