I am trying to use MVC with a controller a view a model and the database.
But I premise I do not know how to use entity framework in my case to connect the model and the database. So I get this runtime error:
"InvalidOperationException: Unable to resolve service for type 'WebCoreFly.Models.FlightsList' while attempting to activate 'WebCoreFly.Controllers.HomeController"
My code consists in:
the controller code:
public class HomeController : Controller
{
private FlightsList l;
public HomeController(FlightsList theList)
{ l = theList; }
public ViewResult Index()
{
return View(l.Flights);
}
}
the Model Code for Flights:
public partial class Flights
{
public long ID { get; set; }
public long Id_Destination { get; set; }
public string Id_Source { get; set; }
public string Nome { get; set; }
public string Company { get; set; }
public System.DateTime Time { get; set; }
public string Id_Plane { get; set; }
public Nullable<System.DateTime> TimeOfArrival { get; set; }
}
and the model for FlightsList:
public class FlightsList
{
private FlyDBContext context;
public FlightsList(FlyDBContext ctx)
{
context = ctx;
}
public IQueryable<Flights> Flights => context.Flights;
}
finally I have defined my dbcontext:
public class FlyDBContext : DbContext
{
public FlyDBContext(DbContextOptions<FlyDBContext> options)
: base(options)
{
}
public DbSet<WebCoreFly.Models.Passengers> Passengers { get; set; }
public DbSet<WebCoreFly.Models.Bookings> Bookings { get; set; }
public DbSet<WebCoreFly.Models.Flights> Flights { get; set; }
}
And in my startup code, I configure services to accept my dbcontext with a link to Existing SQL Database called Fly:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<FlyDBContext>(options =>
options.UseSqlServer(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Fly;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"));
}
And this is the Configure method of startup:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
My question is: who is responsible to pass to my controller the flights list? and since the flightlist is tied to the dbcontext, is the problem somehow related to the fact I did not use entityframework? (For semplicity Idid not post the code for my view, but I can do it if necessary)
the issue is coming because of the dependency Injection. Here How the application would know that Flights List object requires in Home Controller. To fix this you have to configure it in StartUp.Cs class Configure Service method.
services.AddSingelton<FlightsList>();
There are various ways to configure it like Transient, AddScoped etc.
It is better if you use repository pattern here. Register here the Interface. like following.
services.AddSingelton<IRepository, FlightsList>();
In controller side.
public class HomeController : Controller
{
private IRepository l;
public HomeController(IRepository theList)
{ l = theList; }
public ViewResult Index()
{
return View(l.Flights);
}
}
Hope it will help.
I created the new asp mvc core 2.0 angular template and added models and dtos which I want to map in the controller with Automapper. I included automapper 6.1.1 . When I navigate to http://localhost:61031/api/classes it gives me the exception Missing type map configuration or unsupported mapping. I read through many posts but are unable to find what is going on.
My code is as follows:
Overview of project
MODELS
Models.Classes.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.Models
{
public class Classes
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string ClassName { get; set; }
[Required]
[Range(1, 50)]
public int MaxStudents { get; set; }
public ICollection<Students> Students { get; set; } = new List<Students>();
}
}
Models.Students.cs
using System;
namespace WebApplication1.Models
{
public class Students
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Gender Gender { get; set; }
public Classes Classes { get; set; }
public int ClassId { get; set; }
}
}
Models.EdulyContext.cs
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.Models
{
public class EdulyContext : DbContext
{
public EdulyContext(DbContextOptions<EdulyContext> options) : base(options)
{
Database.Migrate();
}
public DbSet<Classes> Classes { get; set; }
public DbSet<Students> Students { get; set; }
}
}
DTOS
Dto.ClassesDtos.ClassesDto.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApplication1.Models;
namespace WebApplication1.Dto.ClassesDtos
{
public class ClassesDto
{
public string ClassName { get; set; }
public int MaxStudents { get; set; }
public ICollection<Students> Students { get; set; } = new List<Students>();
}
}
Dto.StudentsDtos.StudentDto.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApplication1.Models;
namespace WebApplication1.Dto.StudentsDtos
{
public class StudentsDto
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Gender Gender { get; set; }
public Models.Classes Classes { get; set; }
public int ClassId { get; set; }
}
}
CONTROLLERS
Controllers.ClassesController.cs
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApplication1.Dto.ClassesDtos;
using WebApplication1.Repositories.Interfaces;
namespace WebApplication1.Controllers
{
[Route("api/classes")]
public class ClassesController : Controller
{
private IClassesRepository _classesRepository;
public ClassesController(IClassesRepository classesRepository)
{
_classesRepository = classesRepository;
}
[HttpGet()]
public IActionResult GetClasses()
{
var classesEntities = _classesRepository.GetClasses();
var results = Mapper.Map<ClassesDto>(classesEntities);
return Ok(results);
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace WebApplication1
{
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
host.Run();
}
public static IWebHost BuildWebHost(string[] args)
{
return new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((builderContext, config) =>
{
IHostingEnvironment env = builderContext.HostingEnvironment;
})
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
}
}
Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.Webpack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebApplication1.Models;
using WebApplication1.Dto;
using Microsoft.EntityFrameworkCore;
using WebApplication1.Repositories.Interfaces;
using WebApplication1.Repositories;
namespace WebApplication1
{
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.AddMvc();
var connectionString = #"server=(localdb)\mssqllocaldb;Database=EdulyDbCore2;Trusted_Connection=True";
services.AddDbContext<EdulyContext>(o => o.UseSqlServer(connectionString));
services.AddScoped<IClassesRepository, ClassesRepository>();
}
// 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();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Models.Classes, Dto.ClassesDtos.ClassesDto>();
cfg.CreateMap<Dto.ClassesDtos.ClassesDto, Models.Classes>();
cfg.CreateMap<Models.Students, Dto.StudentsDtos.StudentsDto>();
cfg.CreateMap<Dto.StudentsDtos.StudentsDto, Models.Students>();
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
}
}
In the startup I mapped both directions from classes to classesDto just to be certain. If anyone has any idea what I am doing wrong, help would be much aprreciated. Cheers!
After taking a small break I suddenly realized my mistake.
In classes controller the get return type should be an IEnumerable
so:
var results = Mapper.Map(classesEntities);
should become:
var results = Mapper.Map>(classesEntities);
I am trying to update my database by using automatic migrations. I have recently added some properties to the Identity Model:
namespace CISC_Website.Models
{
public class ApplicationUser : IdentityUser
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool ConfirmedEmail { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("CISCDb")
{
}
}
}
However whenever I run the update-database command these changes are not pushed as my user tables are still the same as when they were first created.
Here is the contents of my migrations folder:
namespace CISC_Website.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Collections.Generic;
internal sealed class Configuration : DbMigrationsConfiguration<CISC_Website.Models.CISCDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CISC_Website.Models.CISCDb context)
{
//seed data...
}
}
}
I know originally when the enable migrations command was run, the identity model was represented as such:
namespace CISC_Website.Models
{
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
}
Any idea how i can get these tables recognized??
Your application has two DbContexts: CISCDb and IdentityDbContext and you have configured migrations only for your CISCDb context. Therefore changes in the Identity context are not included in the CISCDb migrations.
You should be able to configure the migrations for the IdentityContext the same way you did for the other context to get it working.
Hi I am learning to develop project using code first approach. I am facing a small problem that when i run the command Add-Migration its not identifying the changes even i have enables the AutomaticMigrationsEnabled in config file
here is my code
----------------------------- DbContext file
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EntityCodeFirstSample.DataBaseFiles
{
class EntityCodeFirstSampleContext : DbContext
{
public EntityCodeFirstSampleContext()
: base("name=DbConnectionString")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<EntityCodeFirstSampleContext, EntityCodeFirstSample.Migrations.Configuration>("DbConnectionString"));
}
public DbSet<Publisher> Publishers { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Sample> Samples { get; set; }
public DbSet<Venkat> Venkats { get; set; }
}
}
----------------- Configurations file ---------------------------------
namespace EntityCodeFirstSample.Migrations
{
internal sealed class Configuration : DbMigrationsConfiguration<EntityCodeFirstSample.DataBaseFiles.EntityCodeFirstSampleContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(EntityCodeFirstSample.DataBaseFiles.EntityCodeFirstSampleContext context)
{
}
}
}
------------------------------------------- Model File ---------------------
namespace EntityCodeFirstSample.DataBaseFiles
{
[Table("Venkat")]
public class Venkat
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public int NotaryCode { get; set; }
}
}
After running the command Add-Migration VenkatClass it is generating the migration file as below
namespace EntityCodeFirstSample.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class VenkatClass : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
when AutomaticMigrationsEnabled = true then you don't have to add Migration because when you will execute your program the EF will look after for any change on the fly and update your database. If you want to control then set the AutomaticMigrationsEnabled = false. Then you should be able to see the difference when Add-Migration is being called.
Please read: https://msdn.microsoft.com/en-us/data/jj554735.aspx
and then read this: https://msdn.microsoft.com/en-us/data/jj591621.aspx
Run:
update-database
Make sure that the project is set default where the connection string is stored.
If it does not return any error then it is all good to go. You should able to see that the update has already occured and your new changes must have reflect already.
I've been trying to implement a custom version of the new Identity features in ASP.NET 4.5 (Microsoft.AspNet.Identity), using Visual Studio 2013. After many hours of playing around with this, I've simplified my code in an effort to get it running without errors. I've listed my code below. When doing a Local Registration, the database tables are created, but the CreateLocalUser method fails. I'm hoping that someone can help me identify the changes needed.
Models/MembershipModel.cs
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace thePulse.web.Models
{
public class PulseUser : IUser
{
public PulseUser() { }
public PulseUser(string userName)
{
UserName = userName;
}
[Key]
public string Id { get; set; }
[Required]
[StringLength(20)]
public string UserName { get; set; }
[StringLength(100)]
public string Email { get; set; }
[Column(TypeName = "Date")]
public DateTime? BirthDate { get; set; }
[StringLength(1)]
public string Gender { get; set; }
}
public class PulseUserClaim : IUserClaim
{
public PulseUserClaim() { }
[Key]
public string Key { get; set; }
public string UserId { get; set; }
public string ClaimType { get; set; }
public string ClaimValue { get; set; }
}
public class PulseUserSecret : IUserSecret
{
public PulseUserSecret() { }
public PulseUserSecret(string userName, string secret)
{
UserName = userName;
Secret = secret;
}
[Key]
public string UserName { get; set; }
public string Secret { get; set; }
}
public class PulseUserLogin : IUserLogin
{
public PulseUserLogin() { }
public PulseUserLogin(string userId, string loginProvider, string providerKey)
{
LoginProvider = LoginProvider;
ProviderKey = providerKey;
UserId = userId;
}
[Key, Column(Order = 0)]
public string LoginProvider { get; set; }
[Key, Column(Order = 1)]
public string ProviderKey { get; set; }
public string UserId { get; set; }
}
public class PulseRole : IRole
{
public PulseRole() { }
public PulseRole(string roleId)
{
Id = roleId;
}
[Key]
public string Id { get; set; }
}
public class PulseUserRole : IUserRole
{
public PulseUserRole() { }
[Key, Column(Order = 0)]
public string RoleId { get; set; }
[Key, Column(Order = 1)]
public string UserId { get; set; }
}
public class PulseUserContext : IdentityStoreContext
{
public PulseUserContext(DbContext db) : base(db)
{
Users = new UserStore<PulseUser>(db);
Logins = new UserLoginStore<PulseUserLogin>(db);
Roles = new RoleStore<PulseRole, PulseUserRole>(db);
Secrets = new UserSecretStore<PulseUserSecret>(db);
UserClaims = new UserClaimStore<PulseUserClaim>(db);
}
}
public class PulseDbContext : IdentityDbContext<PulseUser, PulseUserClaim, PulseUserSecret, PulseUserLogin, PulseRole, PulseUserRole>
{
}
}
Changes to Controllers/AccountController.cs
public AccountController()
{
IdentityStore = new IdentityStoreManager(new PulseUserContext(new PulseDbContext()));
AuthenticationManager = new IdentityAuthenticationManager(IdentityStore);
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Create a profile, password, and link the local login before signing in the user
PulseUser user = new PulseUser(model.UserName);
if (await IdentityStore.CreateLocalUser(user, model.Password))
{
await AuthenticationManager.SignIn(HttpContext, user.Id, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Failed to register user name: " + model.UserName);
}
}
catch (IdentityException e)
{
ModelState.AddModelError("", e.Message);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
As I said above, this implementation fails when the CreateLocalUser method fails (Microsoft.AspNet.Identity.EntityFramework). I cannot figure out why.
The issue here is that IdentityStoreManager has strong dependency on the default implementation of identity EF models. For example, the CreateLocalUser method will create UserSecret and UserLogin objects and save them to stores, which won't work if the store is not using the default model type. So if you customize the model type, it won't work smoothly with IdentityStoreManager.
Since you only customize the IUser model, I simplified the code to inherit custom user from default identity user and reuse other models from identity EF models.
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace WebApplication11.Models
{
public class PulseUser : User
{
public PulseUser() { }
public PulseUser(string userName) : base(userName)
{
}
[StringLength(100)]
public string Email { get; set; }
[Column(TypeName = "Date")]
public DateTime? BirthDate { get; set; }
[StringLength(1)]
public string Gender { get; set; }
}
public class PulseUserContext : IdentityStoreContext
{
public PulseUserContext(DbContext db) : base(db)
{
this.Users = new UserStore<PulseUser>(this.DbContext);
}
}
public class PulseDbContext : IdentityDbContext<PulseUser, UserClaim, UserSecret, UserLogin, Role, UserRole>
{
}
}
The code above should work with preview version of Identity API.
The IdentityStoreManager API in upcoming release is already aware of this issue and changed all the non-EF dependency code into a base class so that you can customize it by inheriting from it. It should solve all the problems here. Thanks.
PulseUser.Id is defined as a string but doesn't appear to be set to a value. Were you meant to be using a GUID for the Id? If so, initialise it in the constructor.
public PulseUser() : this(String.Empty) { }
public PulseUser(string userName)
{
UserName = userName;
Id = Guid.NewGuid().ToString();
}
You will also want to perform a check that the user name doesn't already exist. Look at overriding DbEntityValidationResult in PulseDbContext. Do a new MVC project in VS2013 to see an example.
Since there are alot of changes on this when going to RTM, i have updated the SPA template that uses a WebApi controller for all the identity signin and such. Its a really cool template , if you havent seen it.
I put all my code here:
https://github.com/s093294/aspnet-identity-rtm/tree/master
(Do note, its only for inspiration. I only made it work and nothing more. Properly have a bug or two also).