Step 1 : Create Resource folder
Step 2 : SharedResources.cs
namespace PillarCore.Api
{
public class SharedResources
{
}
}
Step 3 : Create SharedResources.en-US.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Msg-required" xml:space="preserve">
<value>Api call done</value>
</data>
<data name="model-user-required" xml:space="preserve">
<value>User Name is required.</value>
</data>
</root>
Step 4 : create SharedResources.ja-JP.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Msg-required" xml:space="preserve">
<value>API呼び出し完了</value>
</data>
<data name="model-user-required" xml:space="preserve">
<value>ユーザー名が必要です。</value>
</data>
</root>
Step 5 : create ResourceKeys.cs
public static class ResourceKeys
{
public const string modeluserrequired= "model-user-required";
public const string Msg = "Msg-required";
}
Step 6 : create ValidateModelStateAttribute.cs
namespace PillarCore.Api.Infrastructure
{
#pragma warning disable
public class ValidateModelStateAttribute : ActionFilterAttribute
{
private readonly IStringLocalizer _localizer;
public ValidateModelStateAttribute(IStringLocalizer localizer)
{
_localizer = localizer;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
string _message = string.Join(",", context.ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => _localizer[x.ErrorMessage]).Distinct());
context.Result = new ObjectResult(JsonResponse(1,_message));
}
}
public JsonResponse JsonResponse(int StatusCode, string Message, object Data = null) => new JsonResponse {
StatusCode = StatusCode, Message = Message, Data = Data ?? new object()
};
}
}
Step 7 : ExceptionAttributeFilter.cs //Custome error Exception
namespace PillarCore.Api.Infrastructure
{
#pragma warning disable
public class ExceptionAttributeFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
Common.SetLog(context?.Exception, (controllerActionDescriptor?.ActionName ?? ""));
context.Result = new ObjectResult(JsonResponse(Status.Error, StatusMessage.Error));
base.OnException(context);
}
public JsonResponse JsonResponse(int StatusCode, string Message, object Data = null) => new JsonResponse { StatusCode = StatusCode, Message = Message, Data = Data ?? new object() };
}
}
Step 8 : create model class
public class UserModel
{
[Required(ErrorMessage = ResourceKeys.modeluserrequired)]
public string user{ get; set; }
}
Step 9 : Login method in API
[AllowAnonymous]
[HttpPost("LoginUser")]
public async Task<JsonResponse> LoginUser([FromBody]UserModel value)
{
return JsonResponse("success", _localizer[ResourceKeys.Msg].Value);
}
Step 10 : change in Startup file
private const string defaultResourcePath = "Resources";///Resource folder
public Startup(IConfiguration configuration)
{
Configuration = configuration;
DefaultCulture = Configuration["Configuration:DefaultCulture"] ?? "ja-JP";///Resource defualt language set return Japanese you can set en-US means return English
}
public void ConfigureServices(IServiceCollection services)
{
RegisterLocalizationService(services);
var supportedCultures = GetSupportedCultures();
services.AddMvc(options =>
{
options.Filters.Add(typeof(ValidateModelStateAttribute)); //Set Dynamic validation for invalied argument
options.Filters.Add(typeof(ExceptionAttributeFilter)); ///Set Custome error Exception
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);//.AddJsonOptions(opt => opt.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var supportedCultures = GetSupportedCultures();
app.UseRequestLocalization(new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(DefaultCulture),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseMvc();
}
private void RegisterLocalizationService(IServiceCollection services)
{
services.AddLocalization(options => options.ResourcesPath = defaultResourcePath);
var sharedResourceType = typeof(SharedResources);
services.AddSingleton(x => x.GetService<IStringLocalizerFactory>().Create(sharedResourceType));
}
private List<CultureInfo> GetSupportedCultures()
{
return new List<CultureInfo>
{
new CultureInfo(DefaultCulture)
};
}
Step 2 : SharedResources.cs
namespace PillarCore.Api
{
public class SharedResources
{
}
}
Step 3 : Create SharedResources.en-US.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Msg-required" xml:space="preserve">
<value>Api call done</value>
</data>
<data name="model-user-required" xml:space="preserve">
<value>User Name is required.</value>
</data>
</root>
Step 4 : create SharedResources.ja-JP.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Msg-required" xml:space="preserve">
<value>API呼び出し完了</value>
</data>
<data name="model-user-required" xml:space="preserve">
<value>ユーザー名が必要です。</value>
</data>
</root>
Step 5 : create ResourceKeys.cs
public static class ResourceKeys
{
public const string modeluserrequired= "model-user-required";
public const string Msg = "Msg-required";
}
Step 6 : create ValidateModelStateAttribute.cs
namespace PillarCore.Api.Infrastructure
{
#pragma warning disable
public class ValidateModelStateAttribute : ActionFilterAttribute
{
private readonly IStringLocalizer _localizer;
public ValidateModelStateAttribute(IStringLocalizer localizer)
{
_localizer = localizer;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
string _message = string.Join(",", context.ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => _localizer[x.ErrorMessage]).Distinct());
context.Result = new ObjectResult(JsonResponse(1,_message));
}
}
public JsonResponse JsonResponse(int StatusCode, string Message, object Data = null) => new JsonResponse {
StatusCode = StatusCode, Message = Message, Data = Data ?? new object()
};
}
}
Step 7 : ExceptionAttributeFilter.cs //Custome error Exception
namespace PillarCore.Api.Infrastructure
{
#pragma warning disable
public class ExceptionAttributeFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
Common.SetLog(context?.Exception, (controllerActionDescriptor?.ActionName ?? ""));
context.Result = new ObjectResult(JsonResponse(Status.Error, StatusMessage.Error));
base.OnException(context);
}
public JsonResponse JsonResponse(int StatusCode, string Message, object Data = null) => new JsonResponse { StatusCode = StatusCode, Message = Message, Data = Data ?? new object() };
}
}
Step 8 : create model class
public class UserModel
{
[Required(ErrorMessage = ResourceKeys.modeluserrequired)]
public string user{ get; set; }
}
Step 9 : Login method in API
[AllowAnonymous]
[HttpPost("LoginUser")]
public async Task<JsonResponse> LoginUser([FromBody]UserModel value)
{
return JsonResponse("success", _localizer[ResourceKeys.Msg].Value);
}
Step 10 : change in Startup file
private const string defaultResourcePath = "Resources";///Resource folder
public Startup(IConfiguration configuration)
{
Configuration = configuration;
DefaultCulture = Configuration["Configuration:DefaultCulture"] ?? "ja-JP";///Resource defualt language set return Japanese you can set en-US means return English
}
public void ConfigureServices(IServiceCollection services)
{
RegisterLocalizationService(services);
var supportedCultures = GetSupportedCultures();
services.AddMvc(options =>
{
options.Filters.Add(typeof(ValidateModelStateAttribute)); //Set Dynamic validation for invalied argument
options.Filters.Add(typeof(ExceptionAttributeFilter)); ///Set Custome error Exception
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);//.AddJsonOptions(opt => opt.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var supportedCultures = GetSupportedCultures();
app.UseRequestLocalization(new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(DefaultCulture),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseMvc();
}
private void RegisterLocalizationService(IServiceCollection services)
{
services.AddLocalization(options => options.ResourcesPath = defaultResourcePath);
var sharedResourceType = typeof(SharedResources);
services.AddSingleton(x => x.GetService<IStringLocalizerFactory>().Create(sharedResourceType));
}
private List<CultureInfo> GetSupportedCultures()
{
return new List<CultureInfo>
{
new CultureInfo(DefaultCulture)
};
}
0 Comments