Mvc Core - Multiple custom attributes of the same type found - new scaffoled item - controller with view

April 27, 2019 0 comments
While working on myAttendance.io project in mvc.net core 2.2, I was creating a company and wanted to generate Controller with Views. My company Class is as follows


 public class Company : BaseModel
    {
        public string Logo { get; set; }

        [DisplayName("Company Name")]
        [Required]
        [MaxLength(150)]
        public string CompanyName { get; set; }

        [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Please enter a valid e-mail address")]
        [EmailAddress(ErrorMessage = "Please enter valid email address.")]
        [Required]
        [MaxLength(150)]
        public string Email { get; set; }
        [Required]
        [DataType(DataType.Url)]
        [Url(ErrorMessage = "Invalid URL!")]
        [MaxLength(150)]
        public string Web { get; set; }

        [Phone]
        [Required]
        [MaxLength(15)]
        public string Phone { get; set; }

        [Required]
        [MaxLength(10)]
        public string Currency { get; set; }
        [Required]
        [MaxLength(250)]
        public string Address { get; set; }

    }
When I tried adding New Scaffolded item, I got error saying
 There was an error running the selected code generator: 'Multiple custom attributes of the same type found'

Multiple custom attributes of the same type found

To resolve this error I had to remove
[DataType(DataType.Url)]
If we see model then I have already used
[Url(ErrorMessage = "Invalid URL!")]
This same is applicable for followings
[EmailAddress(ErrorMessage = "Please enter valid email address.")]

[Phone(ErrorMessage = "Please enter valide phone number.")]
We have EmailAddress and PhoneNumber as Datatype also
[DataType(DataType.EmailAddress)]

[DataType(DataType.PhoneNumber)]
So Just make sure we have DataType or corresponding Tag to avoid 'Multiple custom attributes of the same type found.'

InvalidOperationException Unable to resolve service for type Interface while attempting to activate Controller

April 17, 2019 0 comments
A dependency is any object that another object requires, Dependency Injection i.e. DI is used for objects which has complex dependencies. While working on one project in asp.net core 2.2 (MVC project, I came across this error)

An unhandled exception occurred while processing the request.

InvalidOperationException: Unable to resolve service for type 'myproject.Areas.myArea.Interfaces.IHolidayRepository' while attempting to activate 'myproject.Areas.myArea.Controllers.AdminController'.
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

Dependency Injection (DI) is already part of Core framework, We just have to register our dependencies in startup.cs file under ConfigurationService method.

services.AddTransient<IFoo, Foo>();
services.AddSingleton<IBar, Bar>();
services.AddScoped<IHello, Hello>();

ASP.NET services can be configured with the following:

Transient

Always Different - Transient objects are always different; a new instance is provided to every controller and every service.

Scoped

Same within a request - Scoped objects are the same within a request, but different across different requests

Singleton
Singleton objects are the same for every object and every request (regardless of whether an instance is provided in ConfigureServices)

After Registering Dependency Injection in startup.cs file, we will not get InvalidOperationException Unable to resolve service for type Interface while attempting to activate Controller error.

Reference Article - https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2

More than one DbContext named 'myproject.Models.myprojectContext' was found. Specify which one to use by providing its fully qualified name using its exact case

April 15, 2019 0 comments

I was developing a Web-Application in Asp.Net Core 2.2 . After I added the new identity with scaffold it generated me these codes:
For IdentityHostingStartup.cs




[assembly:
 HostingStartup(typeof(myproject.Areas.Identity.IdentityHostingStartup))]
namespace myproject.Areas.Identity
{
    public class IdentityHostingStartup : IHostingStartup
    {
     public void Configure(IWebHostBuilder builder)
      {
      builder.ConfigureServices((context, services) => {
      services.AddDbContext(options =>
       options.UseSqlServer(
       context.Configuration.GetConnectionString("myprojectContextConnection")));

        services.AddDefaultIdentity()
                .AddEntityFrameworkStores();
            });
        }
    }
}

Code in my Startup.cs (After adding Identity I made some modifications in startup.cs, with reference to this article)

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)
        {
            services.Configure(options =>
            {
        // This lambda determines whether user consent for 
       //non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>
        {
        options.AllowAreas = true;
        options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
        options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

      services.ConfigureApplicationCookie(options =>
        {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
        });

        services.Configure(Configuration.GetSection("EmailSettings"));
        services.AddSingleton();
        services.AddScoped();

        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

This was working fine, then I added new models and wanted to scaffold a model with controller and views using Entity Framework. After I set up everything and click ok, I started getting error saying : More than one DbContext named 'myproject.Models.myprojectContext' was found. Specify which one to use by providing its fully qualified name using its exact case.

More than one DbContext was found. Specify which one to use by providing its fully qualified name using its exact case.


 To resolve this issue I removed following lines of code from IdentityHostingStartup.cs

  services.AddDbContext(options =>
   options.UseSqlServer(
   context.Configuration.GetConnectionString("myprojectContextConnection")));

And I modified my startup.cs file to following

 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)
   {
    services.Configure(options =>
      {
      // This lambda determines whether user consent for 
      //non-essential cookies is needed for a given request.
       options.CheckConsentNeeded = context => true;
       options.MinimumSameSitePolicy = SameSiteMode.None;
      });

  services.AddDbContext(options =>
  options.UseSqlServer(Configuration
.GetConnectionString("myprojectContextConnection")));


  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>
    {
    options.AllowAreas = true;
    options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
    options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
     });

   services.ConfigureApplicationCookie(options =>
    {
    options.LoginPath = $"/Identity/Account/Login";
    options.LogoutPath = $"/Identity/Account/Logout";
    options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
     });

    services.Configure(Configuration.GetSection("EmailSettings"));
    services.AddSingleton();
    services.AddScoped();

    }

        // 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();
            }
            else
            {
                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.UseCookiePolicy();
            app.UseAuthentication();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

Now I try generating Scaffold items it works without any error.