Tag Archive | mvc

Configuring Code First migrations for early success

These steps assume you have started with an MVC 4 new project, and that you’re just getting started with MVC/EF. Using automatic migrations is really useful for early development/demos, but when you start to get into ‘professional mode’, read this lovely blog post.

Step 1 Enable migrations

In the nuget package manager console type

enable-migrations -EnableAutomaticMigrations

Step 2 Enable automatic application of migrations

In your application start (or other preferred initialization location). Enter the following code (Replace UsersContext with your database context). Database originates from the System.Data.Entity namespace, and Configuration is from your newly added Migrations namespace.

Database.SetInitializer(new MigrateDatabaseToLatestVersion<UsersContext, Configuration>());

Step 3 Enable automatic drop

In Configuration.cs add this code to the constructor.

AutomaticMigrationDataLossAllowed = true;

 

What does all this do/help with?
The default project does not have migrations automatically enabled. And the error message you receive (if you start querying LINQ objects on your database context) if you don’t will be as follows:
InvalidOperationException
The model backing the 'UsersContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

Enabling migrations sets up the whole migration system. But to enable automatic migrations you have to include -EnableAutomaticMigrations which simply adds the line AutomaticMigrationsEnabled = true; into the newly generated Configurations.cs file.

In conjunction with the database initializer,  development turnaround is more streamlined because you no longer have to type add-migration and update-database every time you make a change. That will happen automatically now. However, that’s not enough, if you want column removals you have to also perform step 3, where automatic data loss is supported.

When you are ready to release software (internally or externally) where you need strict version control and to upgrade databases on site, you should  remove automatic migrations and add a manual migration point.

Advertisements

ASP.NET configuration tool in Visual Studio 2012 – error message on a new MVC project.

If you’ve just launched PROJECT->ASP.NET CONFIGURATION tool from Visual Studio 2012, and experienced this error

System.ArgumentException: The parameter ‘PhysicalDirectory’ is invalid. Parameter name: PhysicalDirectory at System.Web.Configuration.VirtualDirectoryMapping.set_PhysicalDirectory(String value) at System.Web.Configuration.VirtualDirectoryMapping..ctor(String physicalDirectory, Boolean isAppRoot) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, String appPhysPath, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.VerifyAppValid()

You may have a special character in your filenames. In my stituation, I had an ampersand. Move your folder and try again.

On another note – this tool just doesn’t work with MVC 4 apps created with VS2012 out of the box. See here.

Error message: ModelValidationException System.Data.Entity.EdmEntityType: EntityType ‘blah’ has no key defined. Define the key for this EntityType

You may see this error message when adding a controller.

You may see this error message via the debug output, or like this when adding a controller.

There are some simple fixes you can apply when this message occurs.

 // reason 1 - You've forgotten to include a key. All EF models need a key
 public class Item
 {
     public string name { get; set; }
     // just uncomment the line below
     // public int Id {get;set;}
 }
// reason 2 - Class name is not equal to Id member name
public class ItemClass
{
   public int ItemId {get;set;}
   // just change ItemId to Id, or change ItemClass to Item
}
// reason 3 - member does not have getter/setter - it needs to be a property
// If this isn't the Key, you may see a NotSupportedException instead:
//    The specified type member '<name>' is not supported in LINQ to Entities. 
//    Only initializers, entity members, and entity navigation properties are supported.
public class Item
{
   public int ItemId;
   // In the above, just add {get;set;}
}
// reason 4 the Id member is not public
public class Item
{
   // your member must be public
   protected int Id;
}
 // reason 5 - you're confusing Entity Framework
 public class Item
 {
     public int anId { get; set; }
     public int anotherId { get; set; }
 }

 // Just add [Key] to give EF a hint.
 // don't forget-  using System.ComponentModel.DataAnnotations;
 public class Item
 {
     [Key] 
     public int anId { get; set; }
     public int anotherId { get; set; }
 }

As you can see you don’t need the [Key] attribute and many automatic features like cascading delete operations are provided without having to provide attributes and data annotations or the fluent API. See the  conventions for code first development for more information.

Reason 6

A kind reader, Dmitry, below discovered another very odd incarnation of this error and shared it with us.

When creating a new controller with the Visual Studio UI, he accidentally chose his database context class in the edit box where he was supposed to specify his model class.

So EF was complaining that his ProductCtx didn’t have the key! Thanks Dimitry!

 

Reason 7

Another kind reader – Steven Bolens – provided this tidbit for reason 7.

 // reason 7 - you include a [required] property in the entity which is not 
 // natively supported by the Entity Framework
 public class Item
 {
     [Key]
     public int Id { get; set; }
     [Required]
     public Version ItemVersion { get; set; }         
 }

If you omit the Required attribute for the Version (System.Version) the EF simply silently ignores this ItemVersion property when generating the database. But when the property is Required then the EF tries to create a DbSet which is not possible because Version doesn’t have a key. The errormessage I get doesn’t specify that System.Version doesn’t have a key but instead it mentions a Versions class in my model namespace (which doesn’t exist).

Replacing the Version type with a string type (and converting the value to and from string) solves the problem. – Maybe there’s a cunning way around this with attribute decoration or derivation? – Giles

 

Reason 8

An anonymous contributor discovered this problem can also occur if you create the model before you install Entity Framework, even if you have done all the above steps. So make sure you install Entity Framework the first thing you do after you have created your project.

 

Allowing remote access to your IIS Express service

While developing an ASP.NET application with the IISExpress service, you might like to see how it looks on your mobile device connected to your LAN via Wi-Fi, or just any computer connected to your network.

If you do not happen to have the full IIS installed already, you can allow your IISExpress service to serve remote pages quickly and easily by following these steps.

Warning: By following these instructions you are solely liable for any security breach or problems you may face. Do not use this information if you do not agree with that statement.

Assume your machine name is ‘jedi’, and your port number is ‘16253’, replace appropriately.

1. Run a command prompt as administrator, and type in

netsh http add urlacl url=http://jedi:16253/ user=everyone

2. Open up the following file in Notepad or Visual Studio

MyDocuments\IISExpress\config\applicationhost.config

change the binding from:

<binding protocol="http" bindingInformation="*:16253:localhost" />

to:

<binding protocol="http" bindingInformation="*:16253:jedi" />

3. Restart the IISExpress service (use the tray icon or task manager, or a command prompt, type issreset).

4. In Visual Studio, change your Project->Properties->Web settings to launch http://jedi:16253 instead of http://localhost:16253

5. In a web browser on your development machine type http://jedi:16253/

6. Assuming all is good – Open up the port on the firewall.

        • Goto the Windows Firewall with Advanced Security panel
        • Create a new inbound rule
        • Click ‘Port’
        • Click ‘Next’
        • Click TCP
        • Enter a specific port 16253
        • Click ‘Next’
        • Click ‘Allow the connection’
        • Click ‘Next’
        • Click ‘Next’ (you could untick Public)
        • Give it a name “My MVC App” and press Finish.

7. You should now be able to access the page on the mobile device when connected to the Wi-Fi using http://jedi:16253/

For more advanced information see Scott Hansleman’s blog post. Also read some of the comments below where others have found problems and solutions.

The ASP.NET Simple Membership database could not be initialized. – When navigating to a page in an MVC application.

To solve this problem, your fix may be listed here http://go.microsoft.com/fwlink/?LinkId=256588 as described in the exception, but it didn’t help me.

Even though I had two DbContext classes, consolidating those did not help.

My actual problem was that

  • I had renamed the “DefaultConnection” connection string entirely from the project, preferring it to live in my own named connection.
  • I had changed this in all DbContext classes.
  • But  I hadn’t and hadn’t changed the line of code in the \Filters\InitializeSimpleMembershipAttribute.cs class to match.

 

Of course, rather than just replacing the string – I did what a proper programmer should do. I made a constant (or you can expose it as a property of a class).

Can’t see the .mdf file in the App_data folder? #mvc #aspnet

For those who’re following the ASP.NET Movies tutorial from Microsoft and you get to the stage where you are supposed to look at the Movies.mdf data file, you may encounter some problems. There are quite a few, and these issues aren’t unique to the movies sample and can happen to anyone trying to create projects in this way. Here are a list of problems and solutions.

Problem: The database ‘…MVCMOVIE\MVCMOVIE\APP_DATA\MOVIES.MDF’ cannot be opened because it is version 706. This server supports version 655 and earlier. A downgrade path is not supported.

Solution: [It’s likely you’re running Visual Studio Web Developer or VS2010]

  1.  You need to install the SQL Server Data Tools and LocalDB.
  2. Verify the MovieDBContext connection string specified on the previous page of the tutorial.

Problem : “InvalidOperation Exception was unhandled by user code” The supplied SqlConnection does not specify an initial catalog.

Solution: [It’s likely you’re running Visual Studio Web Developer or VS2010]

  1. You need to install the SQL Server Data Tools and LocalDB.
  2. Verify the MovieDBContext connection string specified on the previous page of the tutorial.

Or

  1. You might get away with just adding “Initial Catalog=Movies;” into the connection string.

Problem: The App_Data folder in the solution explorer didn’t contain the .mdf file

Solution:

  1. In the Solution Explorer, click ‘show all files’.
  2. Then click the refresh button.
  3. Then expand the App_Data folder

Problem: The App_Data folder still doesn’t show anything.

Solution:

  1. F5 (Debug) the solution.
  2. Navigate to <location>/Movies in IE- this step populates the database. You could also try using update-database in nuget package manager console.
  3. Go back to visual studio and refresh the App_Data folder.

– This solution applies to other projects, if your .mdf isn’t there or the tables aren’t there, just try navigating to the main DbSet controller class first. This is because the migrations to code first changes are lazily applied. You can write some code in your startup that ensures all pending migrations are added to the database before any other code is run, which is generally handy anyway. I’ll be covering this in another blog post soon.