find a location for property in a new city
Showing posts with label MVC2. Show all posts
Showing posts with label MVC2. Show all posts

Thursday, 19 August 2010

Generate lowercase URLs with T4MVC templating tool

I noticed that my URL paths that are being generated using using T4MVC's excellent MVC templating were coming out in title case. This is a problem since we try to keep all URLs lower case since Google deems URL in different cases showing the same result as duplicate content.

I looked through a lot of the code that is generated by the tool and traced the problem all the way to the MyController.generated.cs file:
public class ActionNamesClass {
    public readonly string Index = "Index";
    public readonly string Edit = "Edit";
    public readonly string Create = "Create";
}

Great now I have to edit the way the code is generated... or do I?

Solution

Turns out David Ebbo has thought of everything! There is a setting in the T4MVC.settings.t4 file specifically for that, which I just need to set to true:
// If true, use lower case tokens in routes for the area, controller and action names
const bool UseLowercaseRoutes = true;

Now when I look at the generated code in my MyController.generated.cs file I can see:
public class ActionNamesClass {
    public readonly string Index = ("Index").ToLowerInvariant();
    public readonly string Edit = ("Edit").ToLowerInvariant();
    public readonly string Create = ("Create").ToLowerInvariant();
}

Lovely.

Follow britishdev on Twitter

Monday, 19 July 2010

System.Data.Entity not referenced when using Entity Framework

I started getting a compilation error telling with a message telling me "CS0012: The type 'System.Data.Objects.DataClasses.EntityObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'". This really confused me since the solution built fine but the error only occurred at run time.

Obviously, it is all about adding a reference to System.Data.Entity to my Web project right? I checked and it is already there. Removed it re-added it. Checked for the correct version but still it doesn't like it! Why?

This came about when I used an existing Models project from a different solution in a brand new MVC 2 web application. So I checked the differences between the working solution and the new solution. Both had the same reference in the Web project so what's wrong?

Solution

Finally, I found that I had to add the System.Data.Entity assembly in the web.config too! See line 6 below:
<compilation debug="true" targetFramework="4.0">
  <assemblies>
    <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </assemblies>
</compilation>

This miraculously made my page start working as expected again.

Follow britishdev on Twitter

Thursday, 24 June 2010

Entity Framework MetadataException: Unable to load the specified metadata resource

I got a "System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation" error with a description of "System.Data.MetadataException: Unable to load the specified metadata resource. at System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources".

This occurred when I was trying to move my Models out of my main MVC web application assembly. The main web dll is called Web and within that project is a folder called Models that is used to store all my *ahem* Models and entity data models etc. I decided to move everything in the Models folder out into its own Models assembly. I edited all the namespaces and everything built okay.

However, I was getting a runtime MetadataException when trying to view the page. What the hell is going on?!

Solution

The problem is that the connection string was incorrect. It wasn't immediately obviously with that error message but when you think about it, it makes sense.

My connection string was: connectionString="metadata=res://*/Models.Messaging.MessagingObjects.csdl|res://*/Models.Messaging.MessagingObjects.ssdl|res://*/Models.Messaging.MessagingObjects.msl;....etc"

Just so you know the metadata represents this metadata=res://{assembly}/{namespace}.{filename}.csdl|res://{assembly}/{namespace}.{filename}.ssdl|res://{assembly}/{namespace}.{filename}.msl;

Since I have moved the models around and the namespace is now different I needed to make it connectionString="metadata=res://*/Messaging.MessagingObjects.csdl|res://*/Messaging.MessagingObjects.ssdl|res://*/Messaging.MessagingObjects.msl;

Just for further understanding I could have replaced the asterix with Models since that is the name of the dll that contains my Messaging models.

Follow britishdev on Twitter

Monday, 21 June 2010

MVC pass ViewMasterPage a Model

I have some data that I would like to display on every page on an MVC site. So my PartialView needs to go in the ViewMasterPage with data passed to it, but how is it possible to pass and then access a ViewModel or Model in a ViewMasterPage.

I found quite a cunning way of doing this by using the ViewMasterPage<T> class instead of ViewMasterPage to model and use the data I need.

Solution

I made a new class called BaseViewModel. This will be the class that all ViewModels should now inherit from. The class looks like this:
namespace Web.ViewModels
{
    public class BaseViewModel
    {
        public string MyProperty { get; set; }
    }
}

I now need to make my ViewMasterPage inherit from the generic version of ViewMasterPage%lt;%gt; taking in my new BaseViewModel by making the top line look like this:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<Web.ViewModels.BaseViewModel>" %>

Now I simply make the ViewModel I was using originally for my View inherit from BaseViewModel and I am ready to start passing data to the ViewMasterPage via MyProperty. The View that used the now modified ViewModel is unaffected and the ViewMasterPage now has access to the new data like so:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<Web.ViewModels.BaseViewModel>" %>
<%: Model.MyProperty %>

Further

This is all great (and very clever and amazing!) but what about when I am not passing a ViewModel to my View I am just sending a Model? I don't want to have to make a new ViewModel containing this model just for the sake of making it inherit from BaseViewModel.

Well, I made a new class that inherits from BaseViewModel that has a Generic constructor that allows me to pass in my Model. This class looks like this:
namespace Web.ViewModels
{
    public class BaseViewModel : BaseViewModel
    {
        public BaseViewModel() { }
        public BaseViewModel(T innerModel)
        {
            InnerModel = innerModel;
        }

        public T InnerModel { get; set; }
    }
}

I will need to change the type that is passed to the View in the Controller from this:
return View(message);
to this:
return View(new BaseViewModel<Message>(message));

I will then have to change the corresponding View so that it inherits from the new ViewModel and references the InnerModel property instead of just Model:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/RootMvc.Master" Inherits="System.Web.Mvc.ViewPage<Web.ViewModels.BaseViewModel<Web.Models.Social.Message>>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="RootContent" runat="server">
    <%: Model.InnerModel.Title %>
</asp:Content>

Now your ViewMasterPage is still getting a ViewModel of type BaseViewModel and your main View still has strongly-typed IntelliSense access to your original Model.

Follow britishdev on Twitter

Monday, 14 June 2010

Make Form Postbacks work with MVC pages inside a WebForm MasterPage

I recently wrote about how I nested an MVC site with in a WebForms MasterPage and it how it all worked perfectly ;) However, I avoided the quite inevitable problem of POSTing not working as expected in your WebForm master page, mainly because I hadn't worked out how. Well I have now found a way and have explained it here:

Problem 1.

You may notice that any inputs above your MVC placeholder will work and any form inputs below your MVC placeholder will not POST.

The problem is that traditional ASP.NET web forms applications work off the principle of having only one form. MVC does not. However, if you look at the rendered HTML you may notice you have more than one form. ASP.NET will cope with the first form up until the first closing form tag (</form>).

Solution
Remove all form tags from your MVC pages that are causing the nested forms. This way there will only be one form per page and should therefore POST correctly. Your MVC pages will continue to POST as expected.

Problem 2.

So now your WebForms MasterPage and MVC page performs postbacks wherever there is a submit button as expected. The problem now is that you are going to have to handle that post back within your MVC page.

Solution
Make a base Controller class that all Controllers in the solution should inherit for. (I deliberately didn't end the class name with Controller so that MVC doesn't try and use it on its own).

Here is the main part of my ControllerBase:
using System.Web.Mvc;
namespace Web.Controllers
{
    public class ControllerBase : Controller
    {
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //if there is a form being posted
            if (Request.Form != null && Request.Form.Count > 0)
            {
                //iterate though all form keys
                for (var i = 0; i < Request.Form.Count; i++)
                {
                    //get the value of the form key/value in question
                    var value = Request.Form[i];
                    //if this is the key/value form pair i want and it is not blank
                    if (Request.Form.Keys[i].EndsWith("txtSiteSearch") && !string.IsNullOrWhiteSpace(value))
                    {
                        //do something (this redirects to a page with the search value in the query string
                        Response.Redirect("/search/?q=" + value);
                    }
                }
            }
            base.OnActionExecuting(filterContext);
        }
    }
}

This will run on every request just before the selected ActionMethod is encountered.

I am essentially looking for a particular form field to check if the user typed into the MasterPage's site search text box (with ID="txtSiteSearch") before clicking a form submit button. If they have I send them to the search page with the search text in the querystring.

Obviously, this example is specific to my needs but if you need the form to use a service or other methods, these are all possible too.

Follow britishdev on Twitter

Tuesday, 8 June 2010

Use WebForms MasterPage in MVC project

Want to avoid having to duplicate your MasterPage design that you made in your ASP.NET WebForms project in you new MVC project? There is a simple way to share your master page across the ASP.NET web forms and MVC projects. Here's how:

Make a new "MVC 2 View Master Page" in your /Views/Shared folder and add the content:
<%@ Master Language="C#" MasterPageFile="~/MasterPages/Root.Master" AutoEventWireup="true" Inherits="System.Web.Mvc.ViewMasterPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="RootTitle" runat="server">
    <asp:ContentPlaceHolder ID="RootTitle" runat="server" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="RootContent" runat="server">
    <asp:ContentPlaceHolder ID="RootContent" runat="server"/>
</asp:Content>

Replace the URL with the destination of your web forms MasterPage and the ContentPlaceHolderIDs with the respective ones you used in your original web forms master page.

You can then go on to use your new MVC master page as you would before but it will inherit all the content from your web forms master page.

Note

Any form post controls on your web forms master page will not work on your MVC pages. I have found a way though which I explained in my post about making form posts work in a webform master page nested MVC page if that sort of thing interests you.

Follow britishdev on Twitter

Friday, 4 June 2010

Don't use runAllManagedModulesForAllRequests="true" when getting your MVC routing to work

It seems to be common advice to make your modules section of your web.config say <modules runAllManagedModulesForAllRequests="true">. In fact this is quite a drastic thing to do to solve the routing problem and has global effects that could CAUSE ERRORS.

You need a module that goes by the name of UrlRoutingModule-4.0 to be running through IIS. Now, since your MVC URLs are likely to end without .aspx these will not be picked up by IIS and run through the intergrated pipeline and therefore you will end up with 404 not found errors. I struggled with this when I was getting started until I found the <modules runAllManagedModulesForAllRequests="true"> workaround.

This highly recommended fix can cause other problems. These problems come in the form of making all your registered HTTP modules run on every request, not just managed requests (e.g. .aspx). This means modules will run on ever .jpg .gif .css .html .pdf etc.

This is:
  1. a waste of resources if this wasn't the intended use of your other modules
  2. a potential for errors from new unexpected behaviour.

Better solution

Fine, so the ranting about <modules runAllManagedModulesForAllRequests="true"> is over. What is a better solution?

In the modules section of your web.config, you can add the UrlRoutingModule-4.0 module in with a blank precondition meaning it will run on all requests. You will probably need to remove it first since it is most likely already registered at machine level. So make your web.config look like this:
<modules>
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
  <!-- any other modules you want to run in MVC e.g. FormsAuthentication, Roles etc. -->
</modules>

Note: the modules element does NOT contain the runAllManagedModulesForAllRequests="true" attribute because it is evil!

Follow britishdev on Twitter

Thursday, 27 May 2010

MVC2 deploy - Could not load file or assembly 'System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies.

A new MVC 2 project worked on my local machine but when it was deployed to the test server it gave the error 'Could not load file or assembly 'System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies.' I have the full Visual Studio 2010 installed on my local machine but just the .NET 4 framework installed on the test servers. It seems the MVC assemblies do not come with .NET 4 framework itself so how to make MVC 2 work on the test servers?

Update This was written for difficulties with deploying an MVC 2 app. I have written a new blog post about deploying an ASP.NET MVC 3 web application to keep you up to date with the new technologies.

When I installed Visual Studio 2010 on my local machine it came with all the fruit included (.NET4 framework, MVC2 etc) so the System.Web.Mvc.dll can be found in my machine's GAC (C:\Windows\assembly). However, since there is no need to bloat the web servers only the plain old .NET4 framework has been installed on the test servers. This does NOT include the MVC assembly and that is why it cannot be found by the web application.

You need this assembly to be on your web servers that you are deploying to but you want to avoid having to copy them into the GAC manually and doing all that gacutil mess or maybe you don't have access to your servers if they are hosted by godaddy or something.

Solution

You need to make the System.Web.Mvc assembly bin deployable... okay that doesn't sound easy but here is how to do it for the necessary MVC references:

Simply right click the reference and select 'Properties':

Then change 'Copy Local' to 'True':

Note

If your server has .NET 3.5 sp1 installed the new(ish) assemblies System.Web.Routing and System.Web.Abstractions will already be in the GAC. If you had previously deployed an MVC 1 application to a .NET 3.5 server you may remember having to deploy the other two assemblies too. Since MVC2 requires at least .NET 3.5 sp1 you will not need to worry about these assemblies, just System.Web.Mvc.

Update

There is an easier way to do this if you are using Visual Studio 2010 Service Pack 1 and using Web Deploy as your publish action when publishing. You can add deployable dependencies to your ASP.NET MVC project that will choose the necessary assemblies for you. Even easier!

Follow britishdev on Twitter

Wednesday, 26 May 2010

How to add an ASP.NET MVC 2 project to an existing ASP.NET Web forms application

In this 'how to' I will demonstrate how to integrate an ASP.NET MVC 2 project to an ASP.NET WebForms application that already exists. There are many weird ungoogleable issues and extra tips that haven't been covered elsewhere. I hope this guide helps you get started.

Update: I have written an updated blog post for the slightly different details of adding to a web forms project with an ASP.NET MVC 3 project.

1. Add references

Right click on your web root project in Visual Studio (2010 in my case) and add the following references:
  • System.Web.Routing
  • System.Web.Abstractions
  • System.Web.Mvc

2. Configuration

Make your web.config look like this. Obviously not exactly like this, don't just paste this over the top of your glorious web.config. I'm just highlighting the necessary points that need to be fitted into your existing web.config:
<system.web>
  <compilation debug="true" targetFramework="4.0">
    <assemblies>
      <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Abstractions,Version=4.0.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Routing,Version=4.0.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"/>
    </assemblies>
  </compilation>
  <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
    <namespaces>
      <add namespace="System.Web.Mvc"/>
      <add namespace="System.Web.Mvc.Ajax"/>
      <add namespace="System.Web.Mvc.Html"/>
      <add namespace="System.Web.Routing"/>
    </namespaces>
  </pages>
</system.web>
<system.webServer>
  <modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
  </modules>
</system.webServer>
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Update: I have changed my recommendation against using <modules runAllManagedModulesForAllRequests="true"> in favour of adding the UrlRoutingModule-4.0 module with a blank precondition as I explain in my article Don't use runAllManagedModulesForAllRequests="true" for MVC routing.

3. Routing

You will need to add a global.asax file to your web application if you haven't already got one. Right click > Add > Add New Item > Global Application Class:


Now in your global.asax add these usings:
using System.Web.Mvc;
using System.Web.Routing;

Now add these lines:
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    //ignore aspx pages (web forms take care of these)
    routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");

    routes.MapRoute(
        // Route name
        "Default",
        // URL with parameters
        "{controller}/{action}/{id}",
        // Parameter defaults
        new { controller = "home", action = "index", id = "" }
        );
}

protected void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);
}

4. Add some standard folders to the solution

Add a folder named 'Controllers' to your web project.
Add a folder named 'Views' to your web project.
Add a folder named 'Shared' to that Views folder.
Add a web configuration file to the Views folder (web.config).
Open this web.config in the Views folder and ensure make its contents as follows:
<?xml version="1.0"?>

<configuration>
  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    
    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

5. Get Visual Studio 2010 to recognise your MVC skills

If you right click the Controllers folder and select Add, you'll notice there is no Controller class to add. You need to make a change to your web project file.

Using Windows Explorer find the web project file (Web.csproj in my case) and open it in a text editor. You will need to add "{F85E285D-A4E0-4152-9332-AB1D724D3325};" to the ProjectTypeGuids element.

E.g. mine now looks like this:
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

6. Optional: Add a Controller (for a laugh)

Back to Visual Studio 2010 and right click the Controllers folder > Add > Controller... call it HomeController.

using System.Web.Mvc;

namespace Web.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewData["Message"] = "This is MVC";
            return View();
        }
    }
}

7. Optional: Add a View (just to show off)

Right click where it says return View(); and select Add View... then click Add.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
        <%: ViewData["Message"] %>
    </div>
</body>
</html>

8. Optional: Try it (just to self-indulge your skills)

Now run you site and go to http://{localhost}/home

I hope this saved you the hours it took me! Please comment if you have any feedback. It would be much appreciated

More reading here if you would like to use an existing WebForms MasterPage in your new MVC project.

Follow britishdev on Twitter

Thursday, 13 May 2010

Getting started with ASP.NET MVC2

About to start a new project using ASP.NET MVC 2 and Entity Framework 4. Where to get started?

I worked through the Nerd Dinner example before which was great but was MVC 1. I found this brilliant code sample and walkthrough of creating a music store using MVC 2 and Entity Framework 4 with this MVC 2 Sample Application.

I have looked over this briefly and am impressed. So I would like to share it with you. Enjoy.

Follow britishdev on Twitter

Wednesday, 21 April 2010

LINQ to SQL - Null value cannot be assigned to a member with type System.Int64 which is a non-nullable value type

I am attempting an InsertOnSubmit and it is failing since "The null value cannot be assigned to a member with type System.Int64 which is a non-nullable value type" This LINQ to SQL is driving me crazy. Please help.

The table in the SQL database has a MessageID column which is a BigInt with primary key (NOT NULL IDENTITY 1 1) no Default.

The field looks like this in the designer file to the dbml:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_MessageId", AutoSync=AutoSync.OnInsert, DbType="BigInt NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 
public long MessageId 
{ 
    get 
    { 
        return this._MessageId; 
    } 
    set 
    { 
        if ((this._MessageId != value)) 
        { 
            this.OnMessageIdChanging(value); 
            this.SendPropertyChanging(); 
            this._MessageId = value; 
            this.SendPropertyChanged("MessageId"); 
            this.OnMessageIdChanged(); 
        } 
    } 
}

So the problem is that null cannot be assigned... right. But I'm not passing null! How can I be? I'm using a long (a value type so can't be null by nature).

One workaround I found was making this field nullable but this feels like a hack since it should never be null. Anyway this just moves the problem to the ID not AutoSyncing OnInsert. (AutoSync=OnInsert is set).

Update and solution

Well it took me a while, I even posted on stackoverflow to no avail but finally worked out the problem and wrote about it in this post about optimistic concurrency exceptions on insert although by this time it has manifested itself in a new way since I'm using Entity Framework.

Follow britishdev on Twitter

Sunday, 7 March 2010

Waiting for VS2010 release date to come. Not long now...

I work on quite an agile environment at work and so it is possible to investigate an upgrade to .NET 4, Visual Studio 2010 etc. In fact I have been asked to investigate such a change (just finding time is the issue).

Of course I am keen to get moving with this but I'm not confident about pushing a change to a platform that is still in release candidate. To be fair, the latest release candidate does come with a "go live" license so if you are confident enough you can download it here. Due to me not being willing to upgrade my work's infrastructure to a release candidate I will wait until Monday 22nd March 2010 when it is released. Launch date is April 12th.

I noticed something though: It seems I've been doing a lot of waiting recently.

There are a lot of technologies that I am interested in and have been patiently waiting for that either come with this VS2010 release or co-incidentally release around the same time:
  • C# 4.0 (22/03/2010)
  • ASP.NET 4 (22/03/2010)
  • Visual Studio 2010 (22/03/2010)
  • SQL Server 2008 R2 (by May 2010)
  • MVC 2.0 (with .NET 4)
  • Entity Framework 4 (with .NET 4)
There is Siverlight 4 too (but I am not interested :P)

Update:

The release date has been delayed until at least the launch date of 12th April 2010. Which you can read about here:
Visual Studio 2010 release date delayed

Follow britishdev on Twitter