Password confirmation field -- extension or composition - asp.net-mvc-2

Good day!
I've, say, simple LINQ2SQL entity called User. I need a profile page where password confirmation field needed. I don't want to add this field to my db or entity. I'd like to add ViewModel class. My firt attempt is like this:
[MyClassLevelAttributeToCheckPasswordAndPasswordConfirmation]
public class ProfileUser
{
public User UserEntity {get; set;}
[DisplayName("Password confirmation")]
public string PasswordConfirmation {get; set;}
}
My User class has its own validation and metadata.
Is there any better solution?
Thanks in advance!

Don't use any of your model classes inside the views. Use plain view models:
[MyClassLevelAttributeToCheckPasswordAndPasswordConfirmation]
public class ChangePasswordViewModel
{
public string Password { get; set; }
[DisplayName("Password confirmation")]
public string PasswordConfirmation {get; set;}
}
As you can see we put only the properties relevant to changing a password view (or whatever view you are implementing). This way you can have a fine grained validation control in the context of the given view. AutoMapper could help you to get back your model from the view model.

Related

Should properties of the model be exposed by the view model?

I have read several articles and tutorials on the MVVM pattern but there is one thing I couldn't find distinct information about. Let's take the following example:
The model contains two fields and properties:
private string username;
public string Username {
get; set;
}
private string password;
public string Password {
get; set;
}
Now, what should the view model contain? Should it only contain an instance of the model or should it also "re-expose" the model's properties?
private Model _model;
public Model Model {
get; set;
}
Or...
private Model _model;
public Model Model {
get; set;
}
public Username {
get { return _model.Username; }
set { _model.Username = value; }
}
I have seen both variants in several articles and now am unsure which way is correct.
There is no general right or wrong answer to this question. It depends on the context and on personal preference.
I personally tend to not expose the model to the view directly. I like to have a ViewModel that is specifically tailored for the view. I don't want to implement anything into model just because the view needs it (and I might be tempted to do so when the the model is exposed to the view).
In my ViewModel, I like to have have as little dependencies on the model as possible. If I can get away with it, I like to have a ViewModel that does not have a direct dependency to the Model at all (and have some external entity/service fill do the mapping).

InverseProperty with Database Migration doesn't work when property is protected or internal

I have the following Entity Models
public class User
{
public virtual long Id{get; set;}
[InverseProperty("Users")]
public virtual ICollection<Tag> Tags { get; protected set; }
}
public class Tag
{
public virtual long Id{get; set;}
internal protected virtual ICollection<User> Users { get; set; }
}
This is pure simple many-to-many relation User & Tag
I'm using Data Migrations. When I execute the command Add-Migration or Update-Database
I get the following error "The InversePropertyAttribute on property 'Tags' on type 'Kigg.DomainObjects.Entities.User' is not valid. The property 'Users' is not a valid navigation property on the related type 'Kigg.DomainObjects.Entities.Tag'. Ensure that the property exists and is a valid reference or collection navigation property."
When I changed the access modifier of Users property in Tag to public it worked fine and the generation is what I want.
From my design point of view I want to hide the Tag.Users property and make it protected or internal to keep it for internal use as I don't want to expose it to public API.
Note: I'm not discussing the my design here. I'm asking if it's possible to do that while Tag.Users is protected or internal?
I don't know how to make it work with data annotations but with Fluent API you can apply and experiment with the trick from here: http://blog.cincura.net/232731-mapping-private-protected-properties-in-entity-framework-4-x-code-first/
For your model it would look like the following:
public class User
{
public virtual long Id{get; set;}
public virtual ICollection<Tag> Tags { get; protected set; }
}
public class Tag
{
public virtual long Id{get; set;}
internal protected virtual ICollection<User> Users { get; set; }
public class PropertyAccessors
{
public static readonly Expression<Func<Tag, ICollection<User>>> Users
= t => t.Users;
}
}
Mapping in FluentAPI:
modelBuilder.Entity<User>()
.HasMany(u => u.Tags)
.WithMany(Tag.PropertyAccessors.Users);
This works and creates the expected many-to-many relationship.
But I am not sure if you can do anything useful with that navigation property. The fact that you have the property protected and virtual lets me guess that you basically want lazy loading support inside of the entity class or derived classes.
The problem is that apparently (according to my tests at least) lazy loading doesn't work for anything else than a public property. The loaded tag is a proxy but the navigation collection is always null (unless the property is public).
Moreover, even eager and explicit loading don't work:
Outside of the Tag class:
// Eager loading
var tag = context.Tags.Include(Tag.PropertyAccessors.Users).First();
// Explicit loading
var tag2 = context.Tags.First();
context.Entry(tag2).Collection(Tag.PropertyAccessors.Users).Load();
Or inside of the Tag class (some method in Tag which gets the context passed):
public DoSomething(MyContext context)
{
// Eager loading
var tag = context.Tags.Include(t => t.Users).First();
// Explicit loading
context.Entry(this).Collection(t => t.Users).Load();
}
In all cases I get an exception that the property Users on entity Tag is not a valid navigation property. (The exception disappears as soon as I make the property public.)
I don't know if adding/removing/updating relationships would work. (I doubt.)
It looks that you can map a non-public navigation property with this approach to generate the expected database schema. But it seems that there is nothing useful you can do with it.
I don't know much about EF5 but you can use the attribute InternalsVisibleToAttribute to make internal members visible to a specific assembly.

Entity Framework code first: DbSets and navigation properties

A little new to EF, so please bear with me if the answer to this is obvious. I'm doing a tutorial that uses EF, and two DbSets are defined like this:
public DbSet<BrokerageAccount> BrokerageAccounts { get; set; }
public DbSet<Customer> Customers { get; set; }
The customer class looks like this-- it's a POCO (some code cut for brevity):
public class Customer
{
public Customer()
{
BrokerageAccounts = new HashSet<BrokerageAccount>();
}
// Primitive properties
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Navigation properties
public ICollection<BrokerageAccount> BrokerageAccounts { get; set; }
}
}
The BrokerageAccount class is a POCO as well, very similar in design to Customer.
So far so good. The code I have a question about is below. There is an association made in the main program between Customer and BrokerageAccount that I don't follow. The code reads like this:
public Customer GetCustomer(string custId)
{
using (var context = DataContext)
{
return context.Customers
.Include("BrokerageAccounts").SingleOrDefault(c => c.CustomerCode == custId);
}
}
I can't figure out how the association/join is made between Customer and BrokerageAccount. I don't see any config or other files in my VS 2010 project that tells what associates the two DbSets, what foreign key column to use, etc.
Perhaps I'm missing something obvious or a mapping file of some sort, but just because Customer has an ICollection of BrokerageAccount along with a comment above that says "Navigation Properties", doesn't make it so. In EF, how are those associations established?
The normal way of setting up the navigation properties is to use the ModelBuilder, This gives you a fluent api to set up the associations, take a look at this for some in depth stuff about how you go about this.
http://xhalent.wordpress.com/2011/01/21/configuring-entity-framework-4-codefirst/
Entity framework will guess at what you meant if you dont set up the nav properties manually, in the above case it will probably set up your nav properties as expected as you only have a single 1-* relationship between customer and BrokerageAccount which appears to be named sensibly.
There is also an attribute method that you can use to set up the navigation properties.

Can the Entity Framework Code First generate properly for System.Drawing.Font or Dictionaries?

I am trying to generate a CMS using the Entity Framework Code First. I have a TextBox class that I'd like to have a System.Drawing.Font property or a Dictionary Property. Can the Entity Framework Code First generate properly for System.Drawing.Font or Dictionaries?
EF CF is a code-based ORM (Object-Relational Mapper). It handles the storage and retrieval of data held in classes in your app to and from tables in a database.
If you want to store/retrieve data from your forms, you should create "model" classes - these are just simple classes that contain properties for the values you want to store in your DB. For example:
public class Page
{
public Guid ID {get; set;}
public string Title {get; set;}
public string Body {get; set;}
public string FontName {get; set;}
public int FontSize {get; set;}
}
You then create a DbContext class that contains DbSet instances of the type of your model classes:
public class StorageContext : DbContext
{
public DbSet<Page> Pages {get; set;}
}
Now, EF will figure out the structure of the data you want to store and handle all the DB operations to load/store your data to your DB.
You should be able to write pretty much all your model and DB code (in a separate library in case you need to reuse).
Note: I also strongly encourage you to add an additional level of abstraction and create a Repository class so that your UI code needs know nothing about HOW you're storing your data - this will allow you to change to a completely different storage engine later without having to touch your app code! For example:
public class PageRepo
{
StorageContext _ctx = new StorageContext();
public Page GetPageById(Guid id)
{
...
}
public void StorePage(Page page)
{
...
}
}
You then use your StorageContext (or, better still, your repository) and Model classes to get/store data from/to your DB and copy those values into the necessary fields in your forms, peprforming any data validation before you store data, of course ;)
HTH.
Entity framework allows you to only map few predefined types. That is because it is an ORM and data types that are common to many RDBMS are supported. You can how ever break the complex type such as Font to its primitive properties and map to an entity.
Eg
public class Style
{
public Guid ID {get; set;}
public string FontName {get; set;}
public int FontSize {get; set;}
// other properties
}
In your UI layer you would have a TextBox that will use the style to build a Font.
public class TextBox
{
public TextBox(Style style)
{
Style = style;
}
protected Style Style {get; set;}
public Font FontSize { get { return new Font(Style.FontName, Style.FontSize); } }
// other properties
}

mvc3 entity object with extra field not saved

I am writing an mvc3 application with Entity. I am brand new to .net and entity, so this question may be basic.
I have a model in that represents an object that gets saved to the database. But I would like to have an extra field display on the create and edit forms that is not saved to the database.
Is there a way to specify that a field is not saved with the rest of the object? Also, is there a way to make a field required on create and not on edit?
I would just hard code it, but I would like to include it in the validation that can be set on the entity models.
I am using Entity code first.
you can use viewmodels for displaying or editing, while saving map your view model to domain model(excluding the non-desired fields) and then save it. You can use a tool auto mapper to map your view models to domain models.
say for example you have a domain class person
public class Person
{
public string Name {get; set;}
public string Address {get; set;}
}
then you make a view model
public class VMPerson
{
public string Name {get; set;}
public string Address {get; set;}
public int Age{get;set;}
}
fetch data into your view model and pass it to your view the query may look like
var q = (from p in db.Person
select new VMPerson{
Name = p.name,
Address = p.address,
Age = 16
}).SingleOrDefault();
return q;
in your view the age will also be displayed, then on post
[HttpPost]
public ActionResult Person(VMPerson vmperson)
{
Person p = new Person()// your domain object
// mapping part here
p.name = vmperson.name;
p.address = vmperson;
TryUpdateModel(p);
db.Person.Save();
}