MVC4 Scaffolding Add Controller gives error "Unable to retrieve metadata..." - asp.net-mvc

I'm using RTM version of Windows 8 and VS 2012 Ultimate. I have a MVC4 project using SqlCe 4.0 with a code first entity framework model.
Model is very simple:
public class MyThing
{
public int MyThingId { get; set; }
public int UserId { get; set; }
public string Title { get; set; }
public string Address { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
}
When I try to create a new controller with the built in scaffolding too I get the following error:
"Unable to retrieve metadata for MyThing"
"Using the same DbCompiledModel to create contexts against different
types of database servers is not supported. Instead, create a
separate DbCompiledModel for each type of server being used.
How do I get scaffolding to work?

By trial and error I found the line of code (it's the DbContext ctor) that is causing the error:
public class MyThingDb : DbContext
{
// If I comment this constructor out the scaffolding works
public MyThingDb()
: base("DefaultConnection")
{
}
public DbSet<MyThing> Things{ get; set; }
}
WTF?

I also stumbled into this symptom while running a tutorial on the subject of building an MVC Music Store application.
There definitely seem to be a bug within Visual Studio. What seems to trigger this bug is choosing some name, other than the default, used for the connection string.
My thanks goes to user dwaynef on http://forums.asp.net/t/1838396.aspx/1 for finding this workaround.
A bit elaborated you need to, temporarily during addition of the new scaffolding controller, change the name of your connection string to 'DefaultConnection' in web.config:
<connectionStrings>
<add name="DefaultConnection" ... />
</connectionStrings>
If you have more than one connection string - make sure only this one is there while performing the action.

Here's my two cents worth. I don't believe your solution actually addresses the real issue. The real fix is to pass the base constructor the database name rather than the connection string name so if your connection string is
<add name="MyContext" connectionString="Data Source=|DataDirectory|MyDatabase.sdf" providerName="System.Data.SqlServerCe.4.0" />
you're context class should be defined as
public class MyContext : DbContext
{
public MyContext() : base("MyDatabase") { }...
Hope this works for you and others as it does for me.

Here is what worked for me:
Go to connection string in web.config change the following:
providerName="System.Data.SqlClient"
instead of
providerName="System.Data.SqlServerCe.4.0"
Generate your controller.
Rename providerName back to "System.Data.SqlServerCe.4.0".
run your project.

Works for me:
In the "Add New Scaffolded Item" dialog, i added a new context (plus) with any name (for me "ScaffoldingContext").
Then the scaffolding works. Just rename the context in the Controller.

After trying different options, the below method resolves the error..
If the name value in connection string matches with the value passed to the constructor, it works.
public MyThingDb()
: base("name=MyContext")
{
}

Problem may be because of missing
[NotMapped] Attribute
in one of the model class.
As I missed the attribute and I was cunning my head.
[Display(Name="Logo")]
[DataType(DataType.Upload)]
[NotMapped]
public HttpPostedFileBase Logo { set; get; }

This may sometimes be caused by an association property or a foreign key attribute

I had a similar issue but it wasn't the default constructor. It also happens if you have multiple projects in your solution and your "Web" facing MVC project does not reference EntityFramework.

Change "Things" inside
public
DbSet<MyThing> Things
{ get; set; }
}
to
"Database1" where "Database1" is the name of the database file on disk which appears in your Web.config file as "Database1.sdf"

The solution that worked for me is to pass the same database name as in your connection string to the base constactor of your dbContext class.

I solved this by pressing CTRL+F5 to rebuild my project before adding my controller.

I had a similar issue when trying to create a view from my controller using the scaffolding. In the create view dialog I simply cleared the "Data Context Class" dropdown and then the scaffolding mechanism worded fine.

This is what that worked out for me ..
I commented out the connectionstring using the 'System.Data.SqlServerCe.4.0' and
then added the controller with scaffolding templates.

In your context class you have to comment the DbConfigurationType when you are going to create a controller with scaffolding.
//[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class NameDbContext
{}

MVC 5 / EF 6
perhaps you can do this in the older version?
commented out the connection strings in the web / app.config then save
try to create new controller and have VS create a "new" dbcontext item instead of choosing the one you already have
click create
delete new dbcontext class
replace controller dbcontext with yours
uncomment connection strings in web / app.config then save
worked for me!

I had the same error message, but it was nothing to do with the connection string.
It is a very rare case, but hopefully this will help someone. My model name was the same as one of the segments of my namespace name.
For example:
namespace blah.blah.Building
public class Building
I renamed my namespace and fixed all usages and then the t4 scaffolding worked!
Her's another possible solution. You may have to run scaffolding for "dependent" models first. Then work your way up to complicated models that have many dependencies.

Related

moving mvc5 account controller code to separate project

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!

Modeling an existing database

I want to generate a model based on an existing database -- I thought it would be as simple as writing the model, adding a DbContext class, and configuring a connection string:
namespace MyProject.Models
{
public class Account
{
public int Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
}
public class AccountDBContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
}
}
With a simple boilerplate controller
public ActionResult Index()
{
return View(db.Accounts.ToList());
}
The boilerplate view, which I won't post here, which lists all of the members of the db object that we return.
ANd finally, a connection string:
<add name="AccountDBContext" providerName="System.Data.SqlClient" connectionString="[server connection string]" />
Only problem is I don't see any entries being displayed. It's definitely connecting, but not retrieving or displaying the data that the particular DB contains.. am I missing something?
Edit
Ok, so first thing is first: it wasn't connecting. I had a typo in my connection string name. It was hitting the default, and subsequently displaying nothing.
What I am getting now, though, is The model backing the 'AccountDBContext' context has changed since the database was created.
Is this because my model doesn't match exactly to what the database contains?
This is the "Code First with an Existing Database" scenario.
What version of EF are you using?
In EF 4.3 when you let code first create a database for you, it inserts a Migration-History table into the new database. It’s hidden in System Tables.This is equivalent to the EdmMetadata table you got with EF 4.1 & 4.2. But when you already have the database you can use code first migrations. (http://msdn.microsoft.com/en-US/data/jj591621)
Either way you should probably check if such a table exist. If it does you can delete it and then you'll be solely responsible to correctly matching your pocos to the database.
Another quick workaround i have found is putting
Database.SetInitializer<YourContext>(null);
to your Application_Start() in Global.asax
See also this similar question: Entity Framework Code Only error: the model backing the context has changed since the database was created

how to use ef code first with sql server ce in asp.net mvc 4 visual studio 2012

I am trying to create a simple EF code first sample using SQL server compact edition 4.0.
Technologies used include: Visual Studio 2012 Ultimate.
So i created a simple poco class:
namespace MvcApplication2.Models
{
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
}
And a simple context class:
namespace MvcApplication2.Models
{
public class CustomerEntity : DbContext
{
public DbSet<Customer> Customers { get; set; }
}
}
Then I tried to create a controller class with the template: MVC Controller with read/write actions and views using entity framework.
Model class -> Customer
Data context class -> CustomerEntity
I got the following error:
Unable to retreive metadata for ... Using the same dbcompiledmodel to
create contexts against different types of database servers is not
supported. ...
I should say this exact same code worked without problem using LocalDB.
The only difference that I thought was needed, was the addition of the following to the web.config file.
<add name="CustomerEntity"
connectionString="Data Source=|DataDirectory|CustomerEntity.sdf"
providerName="System.Data.SqlServerCe.4.0" />
Am I missing something else?
I know I can't be the only one having this problem.
Your problem in dublicate DB in EF cache and DB in your App_Data. The easiest way to resolve this problem is to comment your default constructor CustomerEntity, to create controller from template and then uncomment it.

How do I use my own Model classes in conjunction with EF entity classes in MVC?

So I am new to MVC and am working now with MVC3 and the Entity Framework. I am currently using a Model/Schema 1st approach as the database already exists. Therefore I create my ADO.NET Entity Data Model (.edmx) and I have all the needed entities in my MVC app. So far so good on all this.
However let's say one of my Entities is a 'Customer' entity. I can see the auto-generated partial class inheriting from EntityObject in MyEntites.Designer.cs. At this point I want to add some custom business logic to my MVC Model. Natuarally I believe the answer is to use my own partial class created in the Model named 'Customer' as well.
I did a lot of searching on this before asking the question and see all kinds of information on POCO, T4 templates, modifying auto-generated code, etc and am lost. Is it a royal pain to add my own business logic and custom code to the auto-generated entities from EF? I certainly don't want to modify the auto generated code over and over.
I need a straight forward explanation to make the proverbial 'light bulb' go on, and then I can take-off from there. Can someone help me answer how to do this please?
Thanks!
Keep your own class code in a different file, but use the same class and namespace. This will help avoid your code being overwritten by the T4 code generator.
Extending Entity Framework Generated Types
You can also add attributes to generated classes by using a meta class:
Adding Attributes to Generated Classes
Those codes are auto-generated and will be over written on each model update or change.
You can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...

How to do ASP.NET MVC Model Validation with DataAnnotations where ViewModel contains objects from an external Web Service?

I would like to use DataAnnotations for basic client and server-side validation of my MVC ViewModels. My ViewModel looks like this:
public class MyViewModel
{
public Client Client1 { get; set; }
public Client Client2 { get; set; }
public Product Product { get; set; }
}
So I would like to check that both client objects have a name and telephone number, the product object has a valid numeric price, etc.
The problem I have is that both Client and Product are proxy types generated by Visual Studio from a web service, so I can't directly add the annotation attributes to their required properties.
I've read about using the MetadataType attribute to specify the meta data in an alternative class (with duplicate properties), but in this case I can't even add that attribute to the Client and Product classes.
Or can I? In the Web References folder where my VS solution is saved, there is a folder for the web service namespace containing a file called Reference.cs, which contains the VS generated code for the proxy types.
If I add the metadata to the classes in here, will this work—or is messing about with the generated code a really bad idea? Or is there just a simpler, cleaner way to do this?
After a bit of hunting I found that this is actually remarkably simple—it was just a case of my not knowing exactly what to search for!
You don't actually need to add the MetadataType attribute to the original class definition: you can add it to an empty partial class of the same type (make sure your partial class is in the same namespace as the original type).
Then you just create a "buddy" class containing your validation rules as you would normally:
using System.ComponentModel.DataAnnotations;
namespace WebServiceNamespace
{
[MetadataType(typeof(ClientMetaData))]
public partial class Client
{
}
public class ClientMetaData
{
[Required(ErrorMessage = "Please enter a name")]
public string Name { get; set; }
[Required(ErrorMessage="Please enter a telephone Number")]
public string Telephone { get; set; }
}
}
This works perfectly with the standard Model Binding and requires no access to the original code for the type, so you can easily set up validation rules with DataAnnotations, even for types which aren't part of your code base.
Modifying the generated code would work, so long as you don't regenerate it and write over your modifications. Other than the chance of losing your work if someone generates the reference, there isn't a reason you can't add the metadata references to the proxy classes.
The other alternative is using custom validation, or create a model that you then map the fields to the proxy objects. Creating a model that isn't based on the Client object would be your safest method.
I think it would be cleaner to create a model and then map the fields using AutoMapper and/or Model Generator Helper ( http://modelhelper.codeplex.com/ ).

Resources