ASP.NET MVC User.Identity.GetUserId() returning wrong GUID - membership-provider

I am calling this method from within a Controller method while logged in as a user, with the standard DefaultMembershipProvider code in MVC5 that comes completely out of the box. Like this:
string LoggedInUsersId = User.Identity.GetUserId();
When debugging, this method call returns a GUID that is completely different to the "Id" field GUID stored in the AspNetUsers table. As I only have one user in this table, I have no idea where this other GUID is coming from?
I thought that the Id field value from the AspNetUsers table would be returned for the currently logged in user when you call User.Identity.GetUserId()?
I am definitely checking the same database/environment and looking at the right place.

Solved!
Thanks to this blog post (see point #2):
https://digitaltoolfactory.net/blog/2013/10/five-things-should-should-know-about-the-new-asp-net-identity-membership-system/
The new MVC5 membership stuff had automatically created a new local database on my laptop called "DefaultConnection" where it had generated and placed all the membership tables and data. So GetUserId() was returning a GUID that lived locally in the AspNetUsers table from that local database which did not exist in my other main database that the application was using! Gah.
So the fix was changing this line inside of IdentityModels.cs:
public ApplicationDbContext() : base("DefaultConnection") { }
to:
public ApplicationDbContext() : base("MyConnectionString") { }
Now it works and everything is saved centrally into my application's main database.

Related

asp.net core Identity user customization

Detail
I am developing web application in asp.net core with Identity. now in my application I have two kind of user. Customer and Partner both have different profile information and login scenario.customer can login from simple signup from web page but partner can signup from different view with different mandatory fields.
Problem
How can I design Schema.
what are the good practices in this case.
What are the drawback.
Code
This is what I have done so far
public class ApplicationUser : IdentityUser
{
public CustomerProfile CustomerProfile { get; set; }
}
Use inheritance:
public class ApplicationUser : IdentityUser {}
public class Customer : ApplicationUser
{
// Customer-specific properties
}
public class Partner : ApplicationUser
{
// Partner-specific properties
}
By default, this will be implemented via STI (single-table inheritance). That means you'll have just your standard AspNetUsers table containing columns for the properties on ApplicationUser and all derived types. A discriminator column will be added to indicate which type was actually saved, which will then be used to instantiate the right type when queried.
For the most part, this works just fine. The one downside is that properties on derived classes must be nullable. The reason is simple: it would be impossible to provide values for Customer columns while saving a Partner and vice versa. However, the properties only need be nullable at the database-level. You can still require that they be set in forms and such via a view model.
The alternative is to use TPT (table-per-type). With this approach, you'll get AspNetUsers, but also Customers and Partners tables as well. However, the tables for the derived types will have columns corresponding only to the properties specific to that type and a foreign key back to AspNetUsers. All common properties are stored there. With this, you can now enforce columns have values at the database-level, but querying users will require a join. To use TPT, you simply add the Table attribute to your class, i.e. [Table("Customers")] and [Table("Partners")], respectively.
The one important thing to keep in mind with using inheritance, though, is that you need to work with the type you actually want to be persisted. If you save an ApplicationUser instance, it will be an ApplicationUser, not a Customer or Partner. In this regard, you need to be careful with using the correct types with things like UserManager which generically reference the user type. Even if you create an instance of Customer, if you save it via an instance of UserManager<ApplicationUser>, it will upcast to ApplicationUser and that is what will be persisted. To create a new Customer, you'll need an instance of UserManager<Customer>. Likewise, for partners.
However, this also works to your benefit, as if you attempt to look up a user from an instance of UserManager<Customer> for example, you will only find them if they are in fact a Customer. In this way, it makes it trivially simple to have separate portals where only one or the other can log in, as you've indicated that you want.

WebAPI + EF5, Entity framework does not recover from a DBUpdateException and requires a full restart of the service

I have two table in my database. Table USER and table USER_ADDRESSES
Table USER has UserID , UserName , HumanName
Table USER_ADDRESSES has UserAddresseID, UserID, Address
The two tables are related through the UserID foreign key.
I am working code first. The POCOs are as one would expect I guess:
Public class User
{
Public guid UserID {get;set;}
Public string UserName {get;set;}
Public string HumanName {get;set;}
}
Public class UserAddress
{
Public guid UserAddressID {get;set;}
Public guid UserID {get;set;}
Public string Address {get;set;}
Public virtual User User {get;set;}
}
If I POST a user, it flows through EF and into the physical database - cool
If I POST a UserAddress with the UserID foreign key properly assigned as the UserID of the above user, the userAddress flows through EF into the physical database - perfect.
Now as I am learning this subject, I like to test scenarios that I know will cause errors… Understanding how something fails often leads to greater understanding (IMHO).
To this end, I repeat the above steps.POST a user, then POST an Address but this time with an empty GUID in the Address.UserID property, something I know will cause SQL server to error on,this time EF gets an error back from the DB and surfaces that error in my controller class as a DbUpdateException, which I then act upon to send back a BadRequest ErrorResponse, this would be fine except now I can post nothing to the DB, If I subsequently try to post new Users EF throws a DbUpdateException on every POST. The only way out of this condition is to Stop debugging the WebAPI project, kill IISExpress and restart everything.
My suspicion is that it is something to do with the tracked entities in dbset.Local it appears this collection is happy to store entities which violate database constraints, and even after the DB has thrown an error EF does not remove the faulted entity from its cache, and I guess that every time I call DataContext.SaveChanges(), EF keeps trying to submit the Faulty address entity that it has in it's bdset.Local property and thus prevents me from submitting anything further to the DB until the whole project is restarted and the various dbset.Local collections are flushed.
Ok I understand that, In my controller class I can prevent some of these issues by evaluating the various properties of the object before submitting them to my repository/UnitOfWork and thus prevent them from getting into dbset.Local in the first place, perhaps there is some decoration I can add to my POCOs such that ModelState.IsValid returns false if UserID == Guid.Empty in the UserAddress Entity??? . But surely EF should be able to recover from DB originated errors, such that if an INSERT statement fails when run against SQL server, EF should remove the faulting Entity from its Local cache of tracked objects. Thus preventing the whole system from requiring a complete restart. The upshot of this is that if I had unique constraints on other non key fields, before I attempt to submit an entity I will have to query the DB to ensure that there are no records in the DB which would result in a DBUdateException from being thrown, that approach seems inefficient to me. I would rather take the error and throw it back to the client for them to consider.
Now perhaps it's my responsibility that on the occurrence of a DbUpdateException to do something to remove the faulted entity from the dbset.Local collection or similar. If that's the case how should I go about this?
As I have been writing this I am left wondering: Should EF not be able to recover from DBUdateExceptions in and of its self!? Without the need for an IIS restart. Or should I build my DB with no constraints what so ever and allow clients to put any old rubbish in there. It's my believe that EF Entity tracking should honour db constraints and prevent faulted entities from getting into the dbset in the first place.
Please guide me on the correct way to recover from a DBUpdateException?

How to prevent user from modifying some fields on the form?

I am using MVC3 and EF4 to write a web application. I am using an action header like below to capture the form values submitted by the user.
<HttpPost()>
Public Function Edit(ByVal prod as Product) As ActionResult
I use the below code for updating the record.
db.Attach(prod)
db.ObjectStateManager.ChangeObjectState(prod, EntityState.Modified)
db.SaveChanges()
I get the submitted values in prod object which I update in the database. The problem is that there are some users who are not allowed to modify certain fields in a Product, say ProductCost. I have disabled the textboxes for such fields in the HTML. But since it is clientside, the user can easily enable it using some tool like Firebug and modify the value.
The only solution I could come up was to retrieve the existing record from the database and copy its ProductCost value into prod.ProductCost. But I don't like firing a query for achieving this. Is there a better way to achieve this?
Edit: I found the below link to update particular fields. How to update only one field using Entity Framework?
You can use the below code to modify a particular field.
context.ObjectStateManager.GetObjectStateEntry(user).SetModifiedProperty("FieldName");
Now the question is do I have to write the above statement for every field the user is able to modify? If yes, suppose the Product model has 10 fields (1 primary key) and the user is allowed to modify all of them except the primary key, I need to write 9 statements?? Is there a method where you can specify multiple properties at once. Or even better something where you specify the properties which are not modified. (Note: I know I can run a loop over an array of field names to avoid writing 9 statements. I am asking for an alternative method and not refactoring the above)
Never trust client data. Always have your server code to validate the input and do appropriate actions.
I would create separate overloads of my Respiratory method update the product in different ways and then check what is the current user's access type, If he is admin, i will call the overload which updates everything, if he is a manager, i will call the method which updates name,imageUrl and price and if he is an employee, i will call the method which updates only name and ImageURL
[HttpPost]
public ActionResult Edit(Product prod)
{
if(ModelState.IsValid)
{
string userType=GetCurrentUserTypeFromSomeWhere();
if(userType=="admin")
{
repo.UpdateProduct(prod);
}
else if(userType=="manager")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl, prod.Price);
}
else if(userType=="employee")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl);
}
return RedirectToAction("Updated",new {id=prod.ID});
}
}

MVC architecture - patterns

I need some help with MVC architecture. I use the following architecture for an object named User.
UserRepository -> IUserRepository -> UserService -> IUserService -> UserController
The User object comes from my database and I'm using EntityFramework. I have a function that returns a list of users Return_All_Users(). One of the fields that gets returned is "UserType". This comes out as a number, but when I show the list in my Index.aspx page, I would like it to show as a string. The number for "UserType" needs to look into a Dictionary to find the string that goes along with the number like "Administrator" and I would like this string to show in my Index page.
How would I go about doing this? I'm currently using this function:
public IEnumerable<User> Return_All_Users()
{
//my code here
}
I had another post for a similar question, and it was suggested that my IEnumerable should return a string, not the User object. I tried that, but then I'm working with a Dynamic model and I didn't want to do that. Nor do I know how to work with a Dynamic model, so I thought maybe there is a better way of doing this.
Should this happen in my UserService? Maybe I need to create a new class called NewUser, and define the UserType as a string, then instantiate a new NewUser and pass the value from User. Before the UserType is passed, I would look in the dictionary and get the correct value for the key.
Should I do that, or is there a better way?
After I posted this question, I just thought of doing this with a stored procedure. Maybe use a stored procedure in my database to return the data, as opposed to looking up my data straight from my database table.
I would create a View Model UserView that was formatted to the representation of how your view would best use that data. You could perform the mapping from User to UserView within your Repository or Controller depending on where you prefer doing this kind of mapping.

MVC3 - Error setting up Controller with Entity framework

The steps I go through...
Add new ADO.NET Entity Data Model > Generate from DB > Setup new connection string to adventureworks db > Next > Select table "DatabaseLog" > Finish. Verify DatabaseLog is visible in the edmx view.
Right click controller > Add controller
TemplateController with read/write actions and views, using Entity
Model class
AdventureWorksDWEntities
Context
New data Context > Accept default name
View
Razor
Click Add.
Produce Error:
"Unable to retrieve metadata for 'DatabaseDocumentor.models.AdventureWorksDWEntities'.
System.Data.Edm.EdmEntityeType: EntityType 'AdventureWorksDWEntities' has no key defined. Define the key for this entitytype.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet 'AdventureWorksDWEntities' is based on type 'AdventureWorksDWEntities' that has no keys defined.
I tried again using AdventureWorks (not AdventureWorksDW) and this time it worked. But, I still don't understand what to pick when generating a controller. I have 3 options:
Template
Here I picked Controller with read/write actions and views, using Entity. This is easy enough to understand. I want to have my tables generated for me so I pick this option.
Model
This is what I want to model. In this case I want to model the "Department" table. So I choose Department.
Context
This one is real fuzzy to me. I chose *Name*Entities. This is the value in the web.config connection strings area. Why do I need to choose my connection string as the context? I only know context as "an object that I use to get to my entities" in C#. So, here it's hard for me to visualize. Do I need to always choose my connection string for the context?
This issue can occur when the Context is not correctly chosen from the dropdown. The context should be the value stored in the web.config
<add name="NamedEntitiesCs1"
that also contains the Model you want to generate.
I found what the issue is...
I have a 3 tiered architiecture I'm using with each of the below projects in one solution.
1.YeagerTech
2.YeagerTechWcfService
3.YeagerTechModel
No matter what, even though my wcf service references my model, the startup project (1) is not "smart" enough to recognize the metadata to create the Controller. In this case, you must include a reference to your project that includes your edmx model.
You must also ensure that the connectionstring also resides in the startup project (1) via the web.config file, in order to get the connection for the metadata.
I found the answer, the model class should have a key, that is an ID property i.e
public int ID { get; set;}
save the changes and the build or rebuild the solution.
That should be able to work out.
your property in your Model for the ID must be declared as public. rebuild and try again, it should work

Resources