DataAnnotationsLocalization for the type located in another assembly in ASP.NET Core MVC 2.1












4















I'm trying to use resource localization in ASP.NET Core MVC 2.1 project to configure validation error messages as described in this article.



I want to separate assemblies in my project in accordance with the onion architecture, to models were in a separate Assembly. Accordingly, the model namespace is different from the host application namespace.
As described here, I call my resource file by the full type name.



However, the messages of the model attributes are not replaced in accordance with the resource files.



What am I doing wrong?



Details:



Model:



using System.ComponentModel.DataAnnotations;

namespace LocalizedAspNetCoreApp.DomainModels
{
public class TestModel
{
[Display(Name = "Value")]
[Required(ErrorMessage = "ValueRequired")]
public string Value { get; set; }
}
}


Sturtup.cs:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace LocalizedAspNetCoreApp.Host
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddDataAnnotationsLocalization();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();

app.UseMvcWithDefaultRoute();
}
}
}


View:



@model TestModel;
@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<form method="post" asp-controller="Home" asp-action="About">
<div asp-validation-summary="ModelOnly"></div>
<div>
<label asp-for="Value"></label>
<input asp-for="Value" />
<span asp-validation-for="Value"></span>
</div>
<div>
<input type="submit" value="Save" />
</div>
</form>


Resources



Project structure



Result










share|improve this question



























    4















    I'm trying to use resource localization in ASP.NET Core MVC 2.1 project to configure validation error messages as described in this article.



    I want to separate assemblies in my project in accordance with the onion architecture, to models were in a separate Assembly. Accordingly, the model namespace is different from the host application namespace.
    As described here, I call my resource file by the full type name.



    However, the messages of the model attributes are not replaced in accordance with the resource files.



    What am I doing wrong?



    Details:



    Model:



    using System.ComponentModel.DataAnnotations;

    namespace LocalizedAspNetCoreApp.DomainModels
    {
    public class TestModel
    {
    [Display(Name = "Value")]
    [Required(ErrorMessage = "ValueRequired")]
    public string Value { get; set; }
    }
    }


    Sturtup.cs:



    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;

    namespace LocalizedAspNetCoreApp.Host
    {
    public class Startup
    {
    public Startup(IConfiguration configuration)
    {
    Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
    services.AddMvc()
    .AddDataAnnotationsLocalization();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    else
    {
    app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseMvcWithDefaultRoute();
    }
    }
    }


    View:



    @model TestModel;
    @{
    ViewData["Title"] = "About";
    }
    <h2>@ViewData["Title"]</h2>
    <h3>@ViewData["Message"]</h3>

    <form method="post" asp-controller="Home" asp-action="About">
    <div asp-validation-summary="ModelOnly"></div>
    <div>
    <label asp-for="Value"></label>
    <input asp-for="Value" />
    <span asp-validation-for="Value"></span>
    </div>
    <div>
    <input type="submit" value="Save" />
    </div>
    </form>


    Resources



    Project structure



    Result










    share|improve this question

























      4












      4








      4








      I'm trying to use resource localization in ASP.NET Core MVC 2.1 project to configure validation error messages as described in this article.



      I want to separate assemblies in my project in accordance with the onion architecture, to models were in a separate Assembly. Accordingly, the model namespace is different from the host application namespace.
      As described here, I call my resource file by the full type name.



      However, the messages of the model attributes are not replaced in accordance with the resource files.



      What am I doing wrong?



      Details:



      Model:



      using System.ComponentModel.DataAnnotations;

      namespace LocalizedAspNetCoreApp.DomainModels
      {
      public class TestModel
      {
      [Display(Name = "Value")]
      [Required(ErrorMessage = "ValueRequired")]
      public string Value { get; set; }
      }
      }


      Sturtup.cs:



      using Microsoft.AspNetCore.Builder;
      using Microsoft.AspNetCore.Hosting;
      using Microsoft.Extensions.Configuration;
      using Microsoft.Extensions.DependencyInjection;

      namespace LocalizedAspNetCoreApp.Host
      {
      public class Startup
      {
      public Startup(IConfiguration configuration)
      {
      Configuration = configuration;
      }

      public IConfiguration Configuration { get; }

      public void ConfigureServices(IServiceCollection services)
      {
      services.AddMvc()
      .AddDataAnnotationsLocalization();
      }

      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
      if (env.IsDevelopment())
      {
      app.UseDeveloperExceptionPage();
      }
      else
      {
      app.UseExceptionHandler("/Home/Error");
      }

      app.UseStaticFiles();

      app.UseMvcWithDefaultRoute();
      }
      }
      }


      View:



      @model TestModel;
      @{
      ViewData["Title"] = "About";
      }
      <h2>@ViewData["Title"]</h2>
      <h3>@ViewData["Message"]</h3>

      <form method="post" asp-controller="Home" asp-action="About">
      <div asp-validation-summary="ModelOnly"></div>
      <div>
      <label asp-for="Value"></label>
      <input asp-for="Value" />
      <span asp-validation-for="Value"></span>
      </div>
      <div>
      <input type="submit" value="Save" />
      </div>
      </form>


      Resources



      Project structure



      Result










      share|improve this question














      I'm trying to use resource localization in ASP.NET Core MVC 2.1 project to configure validation error messages as described in this article.



      I want to separate assemblies in my project in accordance with the onion architecture, to models were in a separate Assembly. Accordingly, the model namespace is different from the host application namespace.
      As described here, I call my resource file by the full type name.



      However, the messages of the model attributes are not replaced in accordance with the resource files.



      What am I doing wrong?



      Details:



      Model:



      using System.ComponentModel.DataAnnotations;

      namespace LocalizedAspNetCoreApp.DomainModels
      {
      public class TestModel
      {
      [Display(Name = "Value")]
      [Required(ErrorMessage = "ValueRequired")]
      public string Value { get; set; }
      }
      }


      Sturtup.cs:



      using Microsoft.AspNetCore.Builder;
      using Microsoft.AspNetCore.Hosting;
      using Microsoft.Extensions.Configuration;
      using Microsoft.Extensions.DependencyInjection;

      namespace LocalizedAspNetCoreApp.Host
      {
      public class Startup
      {
      public Startup(IConfiguration configuration)
      {
      Configuration = configuration;
      }

      public IConfiguration Configuration { get; }

      public void ConfigureServices(IServiceCollection services)
      {
      services.AddMvc()
      .AddDataAnnotationsLocalization();
      }

      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
      if (env.IsDevelopment())
      {
      app.UseDeveloperExceptionPage();
      }
      else
      {
      app.UseExceptionHandler("/Home/Error");
      }

      app.UseStaticFiles();

      app.UseMvcWithDefaultRoute();
      }
      }
      }


      View:



      @model TestModel;
      @{
      ViewData["Title"] = "About";
      }
      <h2>@ViewData["Title"]</h2>
      <h3>@ViewData["Message"]</h3>

      <form method="post" asp-controller="Home" asp-action="About">
      <div asp-validation-summary="ModelOnly"></div>
      <div>
      <label asp-for="Value"></label>
      <input asp-for="Value" />
      <span asp-validation-for="Value"></span>
      </div>
      <div>
      <input type="submit" value="Save" />
      </div>
      </form>


      Resources



      Project structure



      Result







      asp.net-core data-annotations resx






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 26 '18 at 13:04









      W. AndrewW. Andrew

      233




      233
























          1 Answer
          1






          active

          oldest

          votes


















          4














          First of all:



          The path to the resources is determined according to the following template: {RootNamespace}.{ResourceLocation}.{FullTypeName - AssemblyName},
          where
          {RootNamespace} is, in most cases, the name of the Assembly of the type for which the resource is searched,
          {ResourceLocation} - this is usually "Resources",
          {FullTypeName - AssemblyName} is the remainder of the type FullName.



          You can verify this by injecting the type IStringLocalazer<TestModel> into your controller and accessing the indexer with the key of an existing resource (for example, Value in your case).

          The ResourceNotFound property will be set to true and SearchedLocation will reflect the path used to find the resource.



          Therefore, model resource files should be placed in the same Assembly where the model is described by the same path pattern:
          LocalizedAspNetCoreApp.DomainModels/Resources/TestModel.resx



          If the namespace of the type it would be longer than the name of the Assembly, the remaining part should be added to the file name of the resource. For example:
          LocalizedAspNetCoreApp.DomainModels/Resources/Models.TestModel.resx



          Secondly:



          {ResourceLocation} is initialized by default with an empty string.
          To initialize this value, install the package Microsoft.Extensions.Localization:



          install-package Microsoft.Extensions.Localization



          and change ConfigureServices method in Startup.cs:



              public void ConfigureServices(IServiceCollection services)
          {
          services
          .AddLocalization(opts => opts.ResourcesPath = "Resources")
          .AddMvc()
          .AddDataAnnotationsLocalization();
          }





          share|improve this answer
























          • Yes, it worked. Thanks!

            – W. Andrew
            Nov 26 '18 at 13:29











          • Don't mention it. Just accept the answer is right.

            – Vladimir Shiyanov
            Nov 26 '18 at 13:31











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53481759%2fdataannotationslocalization-for-the-type-located-in-another-assembly-in-asp-net%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          First of all:



          The path to the resources is determined according to the following template: {RootNamespace}.{ResourceLocation}.{FullTypeName - AssemblyName},
          where
          {RootNamespace} is, in most cases, the name of the Assembly of the type for which the resource is searched,
          {ResourceLocation} - this is usually "Resources",
          {FullTypeName - AssemblyName} is the remainder of the type FullName.



          You can verify this by injecting the type IStringLocalazer<TestModel> into your controller and accessing the indexer with the key of an existing resource (for example, Value in your case).

          The ResourceNotFound property will be set to true and SearchedLocation will reflect the path used to find the resource.



          Therefore, model resource files should be placed in the same Assembly where the model is described by the same path pattern:
          LocalizedAspNetCoreApp.DomainModels/Resources/TestModel.resx



          If the namespace of the type it would be longer than the name of the Assembly, the remaining part should be added to the file name of the resource. For example:
          LocalizedAspNetCoreApp.DomainModels/Resources/Models.TestModel.resx



          Secondly:



          {ResourceLocation} is initialized by default with an empty string.
          To initialize this value, install the package Microsoft.Extensions.Localization:



          install-package Microsoft.Extensions.Localization



          and change ConfigureServices method in Startup.cs:



              public void ConfigureServices(IServiceCollection services)
          {
          services
          .AddLocalization(opts => opts.ResourcesPath = "Resources")
          .AddMvc()
          .AddDataAnnotationsLocalization();
          }





          share|improve this answer
























          • Yes, it worked. Thanks!

            – W. Andrew
            Nov 26 '18 at 13:29











          • Don't mention it. Just accept the answer is right.

            – Vladimir Shiyanov
            Nov 26 '18 at 13:31
















          4














          First of all:



          The path to the resources is determined according to the following template: {RootNamespace}.{ResourceLocation}.{FullTypeName - AssemblyName},
          where
          {RootNamespace} is, in most cases, the name of the Assembly of the type for which the resource is searched,
          {ResourceLocation} - this is usually "Resources",
          {FullTypeName - AssemblyName} is the remainder of the type FullName.



          You can verify this by injecting the type IStringLocalazer<TestModel> into your controller and accessing the indexer with the key of an existing resource (for example, Value in your case).

          The ResourceNotFound property will be set to true and SearchedLocation will reflect the path used to find the resource.



          Therefore, model resource files should be placed in the same Assembly where the model is described by the same path pattern:
          LocalizedAspNetCoreApp.DomainModels/Resources/TestModel.resx



          If the namespace of the type it would be longer than the name of the Assembly, the remaining part should be added to the file name of the resource. For example:
          LocalizedAspNetCoreApp.DomainModels/Resources/Models.TestModel.resx



          Secondly:



          {ResourceLocation} is initialized by default with an empty string.
          To initialize this value, install the package Microsoft.Extensions.Localization:



          install-package Microsoft.Extensions.Localization



          and change ConfigureServices method in Startup.cs:



              public void ConfigureServices(IServiceCollection services)
          {
          services
          .AddLocalization(opts => opts.ResourcesPath = "Resources")
          .AddMvc()
          .AddDataAnnotationsLocalization();
          }





          share|improve this answer
























          • Yes, it worked. Thanks!

            – W. Andrew
            Nov 26 '18 at 13:29











          • Don't mention it. Just accept the answer is right.

            – Vladimir Shiyanov
            Nov 26 '18 at 13:31














          4












          4








          4







          First of all:



          The path to the resources is determined according to the following template: {RootNamespace}.{ResourceLocation}.{FullTypeName - AssemblyName},
          where
          {RootNamespace} is, in most cases, the name of the Assembly of the type for which the resource is searched,
          {ResourceLocation} - this is usually "Resources",
          {FullTypeName - AssemblyName} is the remainder of the type FullName.



          You can verify this by injecting the type IStringLocalazer<TestModel> into your controller and accessing the indexer with the key of an existing resource (for example, Value in your case).

          The ResourceNotFound property will be set to true and SearchedLocation will reflect the path used to find the resource.



          Therefore, model resource files should be placed in the same Assembly where the model is described by the same path pattern:
          LocalizedAspNetCoreApp.DomainModels/Resources/TestModel.resx



          If the namespace of the type it would be longer than the name of the Assembly, the remaining part should be added to the file name of the resource. For example:
          LocalizedAspNetCoreApp.DomainModels/Resources/Models.TestModel.resx



          Secondly:



          {ResourceLocation} is initialized by default with an empty string.
          To initialize this value, install the package Microsoft.Extensions.Localization:



          install-package Microsoft.Extensions.Localization



          and change ConfigureServices method in Startup.cs:



              public void ConfigureServices(IServiceCollection services)
          {
          services
          .AddLocalization(opts => opts.ResourcesPath = "Resources")
          .AddMvc()
          .AddDataAnnotationsLocalization();
          }





          share|improve this answer













          First of all:



          The path to the resources is determined according to the following template: {RootNamespace}.{ResourceLocation}.{FullTypeName - AssemblyName},
          where
          {RootNamespace} is, in most cases, the name of the Assembly of the type for which the resource is searched,
          {ResourceLocation} - this is usually "Resources",
          {FullTypeName - AssemblyName} is the remainder of the type FullName.



          You can verify this by injecting the type IStringLocalazer<TestModel> into your controller and accessing the indexer with the key of an existing resource (for example, Value in your case).

          The ResourceNotFound property will be set to true and SearchedLocation will reflect the path used to find the resource.



          Therefore, model resource files should be placed in the same Assembly where the model is described by the same path pattern:
          LocalizedAspNetCoreApp.DomainModels/Resources/TestModel.resx



          If the namespace of the type it would be longer than the name of the Assembly, the remaining part should be added to the file name of the resource. For example:
          LocalizedAspNetCoreApp.DomainModels/Resources/Models.TestModel.resx



          Secondly:



          {ResourceLocation} is initialized by default with an empty string.
          To initialize this value, install the package Microsoft.Extensions.Localization:



          install-package Microsoft.Extensions.Localization



          and change ConfigureServices method in Startup.cs:



              public void ConfigureServices(IServiceCollection services)
          {
          services
          .AddLocalization(opts => opts.ResourcesPath = "Resources")
          .AddMvc()
          .AddDataAnnotationsLocalization();
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 26 '18 at 13:14









          Vladimir ShiyanovVladimir Shiyanov

          881712




          881712













          • Yes, it worked. Thanks!

            – W. Andrew
            Nov 26 '18 at 13:29











          • Don't mention it. Just accept the answer is right.

            – Vladimir Shiyanov
            Nov 26 '18 at 13:31



















          • Yes, it worked. Thanks!

            – W. Andrew
            Nov 26 '18 at 13:29











          • Don't mention it. Just accept the answer is right.

            – Vladimir Shiyanov
            Nov 26 '18 at 13:31

















          Yes, it worked. Thanks!

          – W. Andrew
          Nov 26 '18 at 13:29





          Yes, it worked. Thanks!

          – W. Andrew
          Nov 26 '18 at 13:29













          Don't mention it. Just accept the answer is right.

          – Vladimir Shiyanov
          Nov 26 '18 at 13:31





          Don't mention it. Just accept the answer is right.

          – Vladimir Shiyanov
          Nov 26 '18 at 13:31




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53481759%2fdataannotationslocalization-for-the-type-located-in-another-assembly-in-asp-net%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Contact image not getting when fetch all contact list from iPhone by CNContact

          count number of partitions of a set with n elements into k subsets

          A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks