Sup guys, im有这个麻烦一段时间,不知道该怎么办了。
我有一个重置密码的页面,这是一个剃刀页面。
@page
@model Project.API.Pages.ResetarSenhaModel
@{
Layout = null;
var sucesso = Request.Query["sucesso"].FirstOrDefault();
var mensagem = Request.Query["mensagem"].FirstOrDefault();
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Reset Password</title>
</head>
<body>
@if (mensagem == null)
{
<h1>Reset your password</h1>
<form action="Auth/ResetPassword" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" name="Token" value="@Request.Query["Token"]" />
<input type="hidden" name="Email" value="@Request.Query["Email"]" />
<table>
<tr>
<td>
Senha
</td>
<td>
<input type="password" name="NovaSenha" />
<span asp-validation-for="NovaSenha" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
Confirmar Senha
</td>
<td>
<input type="password" name="ConfirmarNovaSenha" />
<span asp-validation-for="ConfirmarNovaSenha" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Reset" />
</td>
</tr>
</table>
</form>
}
else
{
if (sucesso.Equals("True"))
{
<h1>@mensagem</h1>
}
if (sucesso.Equals("False"))
{
<h1>@mensagem</h1>
}
}
</body>
</html>
在提交时调用这个动作。
[HttpPost]
public async Task<IActionResult> ResetPassword([FromForm]ResetarSenhaVM resetarSenhaVM)
{
try
{
if (ModelState.IsValid)
{
var resultado = await _autenticacaoService.ResetarSenha(resetarSenhaVM);
if (resultado.sucesso)
return RedirectToPage("/ResetarSenha", new {
sucesso = resultado.sucesso,
mensagem = resultado.mensagem});
return RedirectToPage("/ResetarSenha", new {
sucesso = resultado.sucesso,
mensagem = resultado.mensagem});
}
return RedirectToPage("/ResetarSenha");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
然后,每当我提交的形式,我不能得到的验证属性错误消息 在span标签,相反,我得到了一个json。
{
"errors": {
"NovaSenha": [
"The NovaSenha field is required.",
"Password length is between 6 and 50."
]
},
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "0HLJIO56EGJEV:00000001"
}
我缺少什么?任何建议都可以帮助,谢谢
我的startup.cs。
public class Startup
{
public static IConfiguration Configuration { get; set; }
public static IHostingEnvironment HostingEnvironment { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PersisteContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddAutoMapper(typeof(MappingProfile));
RepositoryScopeInjector.Add(services);
ServiceScopeInjector.Add(services);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<ILogger>(LogManager.GetCurrentClassLogger());
services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder => builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod());
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = Configuration["JwtIssuer"],
ValidAudience = Configuration["JwtIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"])),
ClockSkew = TimeSpan.Zero
};
cfg.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
// Add the access_token as a claim, as we may actually need it
var accessToken = context.SecurityToken as JwtSecurityToken;
if (accessToken != null)
{
ClaimsIdentity identity = context.Principal.Identity as ClaimsIdentity;
if (identity != null)
{
identity.AddClaim(new Claim(ClaimTypes.Role, accessToken.Claims.Where(c => c.Type == ClaimTypes.Role).First().Value));
identity.AddClaim(new Claim("id", accessToken.Claims.Where(c => c.Type == "id").First().Value));
identity.AddClaim(new Claim("nome", accessToken.Claims.Where(c => c.Type == "nome").First().Value));
identity.AddClaim(new Claim("email", accessToken.Claims.Where(c => c.Type == "email").First().Value));
}
}
return Task.CompletedTask;
}
};
});
services.AddApiVersioning(options =>
{
options.UseApiBehavior = false;
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ApiVersionReader = ApiVersionReader.Combine(
new HeaderApiVersionReader("x-api-version"));
});
services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
if (!HostingEnvironment.IsProduction())
{
services.AddSwaggerGen();
services.ConfigureOptions<ConfigureSwaggerOptions>();
}
#if !DEBUG
services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddAuthorization()
.AddJsonFormatters()
.AddApiExplorer();
#else
services.AddMvcCore(opts =>
{
opts.Filters.Add(new AllowAnonymousFilter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonFormatters()
.AddApiExplorer();
#endif
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/Home";
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IApiVersionDescriptionProvider apiVersionDescriptionProvider)
{
//Usa appsetings.json de acordo com o ambiente de desenv. que está selecionado
var builder = new ConfigurationBuilder()
.SetBasePath(HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{HostingEnvironment.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
app.UseCors("AllowMyOrigin");
var usCulture = new CultureInfo("en-US");
var supportedCultures = new[] { usCulture };
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseHttpContext();
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(usCulture),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "")),
RequestPath = "",
});
app.UseAuthentication();
if (!HostingEnvironment.IsProduction())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"../swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}
c.RoutePrefix = "bmdoc";
});
}
app.UseMvc();
}
}
}
所以在几个小时后,我得到了我想要的东西。我正在寻找一些关于剃须刀的文档,发现这个链接非常有用,回答了我的大部分问题。https:/docs.microsoft.comen-usaspnetcorerazor-pages?view=aspnetcore-3.1&tabs=visual-studio。
简单解释一下我的做法。
首先,我开始使用我的razor生成的类(在我的例子中是ResetPassword.cshtml.cs),结果是这样的。
public class ResetPasswordModel : PageModel
{
private readonly IAutenticacaoService _autenticacaoService;
public ResetarSenhaModel(IAutenticacaoService autenticacaoService)
{
_autenticacaoService = autenticacaoService;
}
public IActionResult OnGet()
{
return Page();
}
public string Mensagem { get; private set; }
public bool Sucesso { get; private set; }
[BindProperty]
public ResetarSenhaVM resetarSenhaVM { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var resultado = await _autenticacaoService.ResetarSenha(resetarSenhaVM);
this.Sucesso = resultado.sucesso;
this.Mensagem = resultado.mensagem;
return Page();
}
}
}
我使用[BindProperty]来绑定我所有需要验证的类属性到我的razor页面类中,我还导入了我的控制器,它的工作方式(至少)和我之前做的分离控制器一样。
最后在我的html中。
@page
@model Project.API.Pages.ResetPasswordModel
@{
Layout = null;
}
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Reset Password</title>
</head>
<body>
@if (@Model.Mensagem == null && @Model.Sucesso == false)
{
<h1>Reset your password</h1>
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" name="resetarSenhaVM.Token" value="@Request.Query["Token"]" />
<input type="hidden" name="resetarSenhaVM.Email" value="@Request.Query["Email"]" />
<table>
<tr>
<td>
Senha
</td>
<td>
<input
type="password"
name="resetarSenhaVM.NovaSenha"
/>
<span asp-validation-for="resetarSenhaVM.NovaSenha" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
Confirmar Senha
</td>
<td>
<input
type="password"
name="resetarSenhaVM.ConfirmarNovaSenha" />
<span asp-validation-for="resetarSenhaVM.ConfirmarNovaSenha" class="text-danger"></span>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Reset" />
</td>
</tr>
</table>
</form>
}
else
{
if (@Model.Sucesso == true)
{
<h1>@Model.Mensagem</h1>
}
if (@Model.Sucesso == false)
{
<h1>@Model.Mensagem</h1>
}
}
</body>
</html>
最重要的是:记得在你的html文件中使用TagHelper。@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers