我正在尝试在我的ASP.NET Core Web API 2项目中本地化数据注释,我的代码对于普通类非常有效,但不适用于嵌套类C#。我的代码有什么问题吗? .NET Core甚至支持它?
普通班的作品:
namespace ShagerdanehAPI.Models.API
{
public class APIInputs
{
[Required(ErrorMessage = "The {0} field is required.")]
[EmailAddress(ErrorMessage = "The {0} field is not valid.")]
[Display(Name = "Email")]
public string UserName { get; set; }
[Required(ErrorMessage = "The {0} field is required.")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
}
}
但嵌套类无法正常工作
namespace ShagerdanehAPI.Models.API
{
public class APIInputs
{
public class InputLogin
{
[Required(ErrorMessage = "The {0} field is required.")]
[EmailAddress(ErrorMessage = "The {0} field is not valid.")]
[Display(Name = "Email")]
public string UserName { get; set; }
[Required(ErrorMessage = "The {0} field is required.")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
}
}
}
项目结构:
启动类:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder = new IdentityBuilder(builder.UserType, typeof(ApplicationRole), builder.Services);
builder.AddRoleManager<RoleManager<ApplicationRole>>();
builder.AddSignInManager<SignInManager<ApplicationUser>>();
builder.AddEntityFrameworkStores<ApplicationDbContext>();
builder.AddDefaultTokenProviders();
//add Localization
services.AddSingleton<localizationService>();
services.AddLocalization(options => options.ResourcesPath = "Resources");
//add roles
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters()
.AddDataAnnotations()
.AddDataAnnotationsLocalization()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.Configure<RequestLocalizationOptions>(
options =>
{
List<CultureInfo> supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("fa-IR")
};
options.DefaultRequestCulture = new RequestCulture(culture: "fa-IR", uiCulture: "fa-IR");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(context =>
{
string userLangs = context.Request.Headers["Accept-Language"].ToString();
string firstLang = userLangs.Split(',').FirstOrDefault();
string defaultLang = string.IsNullOrEmpty(firstLang) ? "fa-IR" : firstLang;
return Task.FromResult(new ProviderCultureResult(defaultLang, defaultLang));
}));
});
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
services.Configure<ShagerdanehConfig>(Configuration.GetSection("ShagerdanehConfig"));
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
building => building.WithOrigins(
"http://localhost:3000",
"http://192.168.30.2:3000",
AllowAnyMethod()
.AllowAnyHeader()
.SetPreflightMaxAge(TimeSpan.FromMinutes(30)));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
IOptions<RequestLocalizationOptions> locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
app.UseAuthentication();
app.UseCors("AllowSpecificOrigin");
app.UseMvc();
}
}
已发送Json:
答案 0 :(得分:1)
嵌套类的实例应在嵌套外部类中定义。完成验证后,验证就可以正常进行。
我的模特:
public class UserDetailNested
{
// Property Instance in Outer class
public UserInfo UserData { get; set; }
public class UserInfo
{
[Required(ErrorMessage = "The {0} field is required.")]
[EmailAddress(ErrorMessage = "The {0} field is not valid.")]
[Display(Name = "Email")]
public string UserName { get; set; }
[Required(ErrorMessage = "The {0} field is required.")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
}
}
控制器方法:
// POST api/values
[HttpPost]
public IActionResult Post([FromBody]UserDetailNested userDetail)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
else
return Ok();
}
答案 1 :(得分:1)
这是由于嵌套以及期望将译文定位在何处。第一个可行的示例是在resources目录中的APIInputs中寻找翻译。而第二个示例在不存在的APIInputs> InputLogin中查找它。
一种方法是
namespace ShagerdanehAPI.Models.API
{
public class LoginDetails
{
[Required(ErrorMessage = "The {0} field is required.")]
[EmailAddress(ErrorMessage = "The {0} field is not valid.")]
[Display(Name = "Email")]
public string UserName { get; set; }
[Required(ErrorMessage = "The {0} field is required.")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
}
}
然后创建:
namespace ShagerdanehAPI.Models.API
{
public class APIInputs
{
public LoginDetails UserLoginDetails { get; set; }
}
}
您的资源文件应重命名为LoginDetails.fa-IR.resx
您将看到翻译属性在LoginDetails中,而不在APIInputs中,因此就可以看到它。您可以将附加属性添加到APIInputs类中,如果在模型上进行模型验证,则可以像完成APIInputs.fa-IR.resx一样添加资源类,它将从那里获取该属性转换,而其他转换将是从LoginDetails.fa-IR.resx中检索。