I have a solution that contains a WebApi2,MVC5 & DAL project (all RTM).
I am wanting to use the new membership bits that are now baked-in, but I don't like all the account stuff being all in the account controller. Doing a file new project (asp.net) has all of the membership stuff coupled to the account controller.
Within my DAL I am using EF6 as I like the ideal of code-first as it suits what I am trying to do. I am trying to take the account controller code and move it into my separate project.
My context within the DAL is nice and simple (taken from the MVC site)
public class ApplicationUser : IdentityUser
{
//a user can belong to multiple stores
public virtual ICollection<StoreModel> Stores { get; set; }
}
public class DataContext : IdentityDbContext<ApplicationUser>
{
public DataContext(): base("name=DefaultConnection")
{
}
public DbSet<Business> Businesses { get; set; }
public DbSet<ConsumerModel> Consumers { get; set; }
public DbSet<StoreModel> Stores { get; set; }
}
From my account controller within my login actionresult I try
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
It throws an error with User.FindAsync
The entity type ApplicationUser is not part of the model for the
current context.
What do I need to do to allow ApplicationUser to be used in the current context?
I have done something similar. In order to implement separation of concerns, I fetch the UserManager from my Repository and then use it in the Presentation layer. Repository internally creates the UserManager from UserStore using the internal LoginDbContext. That way, the DbContext and Store are separated from the controller.
If you create WebApi project or somthing with VisualStudio template,
please carefully see UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())); in Startup.Auth.cs file.
You might miss (new ApplicationDbContext()) part. By default, it has empty parameter.
You need to create a UserManager which takes in the userstore which takes in your dbcontext
public UserController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public UserManager<ApplicationUser> UserManager { get; private set; }
public UserController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
I believe this will help. I am pretty new to MVC5 and I have been wanting to separate my model layer from my MVC website, mainly because I imagine I will want to share the models across my various projects. I have been unable to follow all the programming mumbo jumbo I have found on the various help sites. I always end up with a lot of errors which I am unable to resolve with my limited knowledge. However, I have found an easy way to move my ApplicationDbContext out of my MVC5 model and with hardly any errors. All the work is done by the wizards already provided by Microsoft. I would like to share my little find with everyone. This is what you do (step by step):
1. Create a MVC5 project with authentication. Call it ModelProject.
2. Exclude everything from the project except
a. Properties
b. References
c. Models
d. packages.config
3. The ModelProject will hold all your models (even ApplicationDbContext.) Rebuild it.
4. Now, create a new MVC5 project with authentication. Call this Mvc5Project
5. Import the ModelProject project into Mvc5Project .
6. Wire the ModelProject into this project i.e. link in the reference.
7. Exclude the following from the MVc5Project from the Models folder
a. AccountViewModels.cs
b. IdentityModels.cs
c. ManageViewModels.cs
8. If you rebuild now, you will get a bunch of errors. Just go to the errors and resolve them using the right click method to get the new namespace from ModelProject. The namespace will show if you have wired the project in correctly.
9. Also, dont forget to go to View/Manage and Views/Account of Mvc5Project and change the models in there to the new location otherwise you will get some weird cryptic errors.
That's it! Now you have a project with the models all separated out (including the applicationDbContext) -And NO ERRORS!! Good luck!
Related
I have an ASP.NET application where users are authenticated using the UserIdentity class. Recently, I have just implemented a soft-delete feature by adding 'ActiveStatus' to the ApplicationUser class.
The issue arises where the user cannot re-register with the soft-deleted email address as a new account. Can someone help me with this?
I've just managed to achieve this in my MVC application using the instructions and sample code from https://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework-6-interceptors.html posted by Rakesh Babu Paruchuri on August 28th, 2015
The sample code link from that blog entry is https://github.com/rakeshbabuparuchuri/EFExpensionPoints
In case those links become unavailable here are the key points:
It uses a custom attribute "SoftDeleteAttribute" with an Entity Framework Interceptor.
The key elements that I included in my own project were:
a class for the SoftDeleteAttribute inherited from System.Attribute
a SoftDeleteQueryVisitor class that inherits from System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.DefaultExpressionVisitor
a SoftDeleteInterceptor class that inherits from System.Data.Entity.Infrastructure.Interception.IDbCommandTreeInterceptor
Then you register the interceptor - in my case I put the following code in the same file as my ApplicationDbContext (inherited from IdentityDbContext):
public class ApplicationDbConfiguration : DbConfiguration
{
public ApplicationDbConfiguration()
{
AddInterceptor(new Helpers.SoftDeleteInterceptor());
}
}
And override OnModelCreating to add a convention for dealing with the SoftDeleteAttribute:
var conv = new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>(
"SoftDeleteColumnName",
(type, attributes) => attributes.Single().ColumnName);
modelBuilder.Conventions.Add(conv);
The final step was adding the SoftDeleteAttribute to my ApplicationUser class.
[SoftDelete("IsDeleted")]
public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IUser<int>
{
//some code removed to emphasise the important bit
[StringLength(150)]
public string Forenames { get; set; }
[StringLength(50)]
public string Surname { get; set; }
public bool IsDeleted { get; set; }
}
In addition to this I've also dropped and re-created the unique index on the Username column of my users table in the database so that it uses a condition so that I can re-use the usernames of deleted users (not recommended but I'm using an existing database):
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[tbl_user] ([UserName] ASC)
WHERE ([IsDeleted]=(0))
I also ran some migrations - I'm not sure if that migrations step is important for getting it to work, I've literally only done this myself today so haven't had a chance to try it against a manually-created database.
With these changes I can soft-delete users and then create new users with the same username and/or email address
I also found a similar solution at http://marisks.net/2016/02/27/entity-framework-soft-delete-and-automatic-created-modified-dates/ which also uses command interceptors, but replaces the SoftDelete Attribute with a fixed column name and has the code arranged a little differently. He does also include updating Created and Modified columns as well as the soft-delete flag. That article references's Rakesh's article which helped me find it :)
I'm trying to implement the simplemembership with my own context class like so:
public class DbInitializer : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<UserProfile> UserProfiles { get; set; }
}
This work fine and I get all the tables I need: Cars , UserProfiles, Webpages.Memberships, Webpages.Roles, WebPages.UserInRoles. But when I move all the model classes to another project and run it I only get Car and UserProfile so I'm wondering what more I have to do to get the rest of the tables?
Take a look at the SimpleSecurity open source project for an example of how to put SimpleMembership in its own context. Additional entities are also added to the project to enhance the security model. This is developed as a class library that can be incorporated into any MVC application.
You did not provide enough information to figure out what went wrong when you moved it to a new project. My guess is that you did not call WebSecurity.InitializeDatabaseConnection. Take a look at this article on customizing SimpleMembership which shows the best way to initialize the database.
I am building a WebApi for a CMS that has its own data provider. No DBContext or entity framework involved.
I have previously used breeze as it being such a breeze to map the server side model to the client:)
I have wondering if I can extend my code or breeze in a way such I get all the stuff from brezejs for free.
What I have to work with is the following Interfaces that I have made implementations for based on the data provider from the CMS.
public interface IC1Repository<T>
{
IQueryable<T> GetAll();
T Add(T item);
void Remove(T item);
bool Update(T item);
}
Its generic, so thats not going to work on the client.
I can generate a context class i guess that holds all the types exposed.
public class mycontext
{
public IC1Repository<Category> Categories { get; set; }
public IC1Repository<Customer> Customers { get; set; }
public IC1Repository<Employee> Employees { get; set; }
}
What would my next steps be to get this workign with breeze. Are there any interfaces i can implement such it mimics the DbContext. Can i maybe crate my custom DbSet that do not talk with a database, but just is a implementation of my IC1Repository above?
Any advices thanks :)
I think you want the ContextProvider which is the base class of the EFContextProvider.
That has the same semantics and same base behavior as the EFContextProvider but it doesn't use EF.
Check out the "No DB" sample which uses the ContextProvider to manage queries and saves to an in-memory "database".
Ignore the fact that this class sits in a DLL with references to EF. I realize that is annoying. But your project will compile and run just fine when there are no EF assemblies around. You can delete all the EF stuff if you used NuGet to get the Breeze.WebApi.dll.
I'm working on a large project using ASP.Net MVC 3, EF 4.1 and Ninject for Dependecy Injection. I've read through many of the existing questions here regarding DDD, EF and the Repository Pattern but I can't seem to find anyone incorporating stored procedures with these patterns.
I don't like the idea of implementing yet another repository pattern on top of what seems to already be a UnitOfWork/RepositoryPattern already defined with a DbContext. Also, I generally don't like the idea of creating Service and Repository classes for every type of entity in the system if possible.
The source of my problem stems from this common repository interface which everyone seems to use.
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(Expression<Func<TEntity, bool>> whereClause);
IEnumerable<TEntity> List();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> whereClause);
void Add(TEntity entity);
void Delete(TEntity entity);
// And so on...
}
That's great if all your queries can be in context of a single entity. Where this breaks for me is when I want to access a stored procedure. With EF 4.1 & Code Generatrion you can add stored procedures (e.g. SelectUser) and it will generate a context which looks something like this.
namespace MyCompany.Data.Database
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using MyCompany.Domain.Entities;
using MyCompany.Domain.Contracts;
public partial class MyCompanyEntities : DbContext
{
public MyCompanyEntities()
: base("name=MyCompanyEntities")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Order> Orders { get; set; }
public DbSet<User> Users { get; set; }
public virtual ObjectResult<User> SelectUser(Nullable<int> userId)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int)); MyCompanyEntities x; x.
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", userIdParameter);
}
public virtual ObjectResult<User> SelectUser(Nullable<int> userId, MergeOption mergeOption)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", mergeOption, userIdParameter);
}
}
}
As part of my DDD setup I have a UserService class and I would like to 'inject' a repository to its constructor. Many examples suggest that the constructor should accept an (IRepository<User> userRepository). This doesn't work for me. Stored procedures are generated on the DbContext class as a method and I am unable to see it.
The only thing I can think of is to either create another interface with the stored procedure methods on it. I don't really want to add it to the generic IRepository because then when you have an instance of IRepository<Order> you'll still see SelectUser which seems a bit odd. Maybe it's not a big deal?
Perhaps I'm going about this the wrong way. Should I not be bothering with creating an interface on top of my DbContext if I'm not trying to create a whole new repository pattern? I was really creating it for the dependency injection. Would it be wrong if the UserService constructor took a MyCompanyEntities instance instead of an interface?
What you found is natural. The problem is that generic repository is insufficient for real scenarios. It is only good for "base" implementation. You need specific repository for User entity which will expose method wrapping call to context exposed stored procedure.
Ok I've just ran into this and I was only supposed to be checking my emails however I've ended up watching this (and not far off subscribing to TekPub).
http://tekpub.com/production/starter
Now this app is a great starting point, but it raises one issue for me and the development process I've been shown to follow (rightly or wrongly). There is no conversion from the LinqToSql object when passing data to the view. Are there any negitives to this?
The main one I can see is with validation, does this cause issues when using MVC's built in validation as this is somthing we use extensivly. Because we are using the built in objects generated by LinqToSql how would one go about adding validation, like
[Required(ErrorMessage="Name is Required")]
public string Name {get;set;}
Interested to understand the benifits of this methodology and any negitives that, should we take it on, experiance through the development process.
Should this be taken as a guide and we should be using ViewModels? If so should we always use them even in simple cases? And how/where in the application logic does the Entity get converted to a ViewModel?
With entity objects, you could use buddy classes, whereby you create a second class which acts as a metadata provider for your entity. For instance, with a Customer entity generated by Linq-to-Sql, I could create a buddy class like so:
[MetadataType(typeof(CustomerMeta))]
partial class Customer {
}
public class CustomerMeta {
[DisplayName("Forename", Required(ErrorMessage = "Forename is required.")]
public string Forename { get; set;}
}
Entities are generated as partial classes so you can add your own code to them.
Alternatively, you could forego pushing your entity types to your views and create specific models based around the functionality required, for instance I would typically have a User entity, but when I need to create a User, I have something called a CreateUserSpec model:
public class CreateUserSpec
{
[DisplayName("Forename")]
public string Forename { get; set; }
}
Which has a subset of the properties of the User, only those required to create a User. This is the model I would pass to my view, and repopulate from the form data. For instance:
public class AccountController
{
public ActionResult Register() {
return View(new CreateUserSpec());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(CreateUserSpec spec) {
if (!ModelState.IsValid) {
return View(spec);
}
var user = UserFactory.CreateUser(spec);
// Redirect to authorisation page?
}
}