Upgrading from MVC 2.0 to MVC 3.0

Have you tried to upgrade an MVC 2.0 application to MVC 3.0, it’s not easy as you need to change a lot of configuration.

Well Eilon Lipton has a codeplex project to make life easier ASP.NET MVC 3 Application Upgrader. This is a standalone application that takes the troubles away for you and delivers an MVC 3.0 application

Mvc3AppConverter.zip (430.58 kb)

mvc crib sheet

Hands-On Labs

 

 

Razor

 

c# code

 

@Html.ActionLink(“Edit”, Edit”, new {id=item.ID})

 

 

implicit code

 

@items

 

Code block

 

@{

       Html.ActionLink(“Edit”, Edit”, new {id=item.ID})

}

 

 

Displaying text inside a code block

 

 

<Text>Review</Text>

 

 

Explicit expression using brackets

 

@(item.Rating)

 

 

This is an email address

 

K@item.Rating

 

if you use an explicit expression you’ll display the values

 

K@(item.Rating)

 

 

 

If you want 

 

@OdeToCode 

 

you can ESC by using 

 

@@OdeToCode

 

 

Visual C# and .NET 4.0 samples

I came across some nice C# samples from Microsoft today providing everything from Hello World, to how to use Yield and how to program Attributes.

Official Visual Studio 2010 Samples for C# 4.0

Worth having a look at if you are a beginner or a seasoned programmer.

Language Samples

The C# 4.0-specific samples are called:

  • Named and Optional
  • Office Sample
  • Python Sample
  • Simple Variance.

Here is the complete list of language samples:

  • Anonymous Delegates: Demonstrates the use of unnamed delegates to reduce application complexity.
  • Arrays: Shows how to use arrays.
  • Attributes: Shows how to create custom attribute classes, use them in code, and query them through reflection.
  • Collection Classes: Shows how to make non-generic collection classes that can be used with the foreach statement.
  • COM Interop Part I: Shows how to use C# to interoperate with COM objects.
  • COM Interop Part II: Shows how to a use a C# server together with a C++ COM client.
  • Commandline: Demonstrates simple command-line processing and array indexing.
  • Condiational Methods: Demonstrates conditional methods, which provide a powerful mechanism by which calls to methods can be included or omitted depending on whether a symbol is defined.
  • Delegates: Shows how delegates are declared, mapped to static and instance methods, and combined into multicast delegates.
  • Events: Shows how to declare, invoke, and configure events in C#.
  • Explicit Interface: Demonstrates how to explicitly implement interface members and how to access those members from interface instances.
  • Generics: Shows how to make generic collection classes that can be used with the foreach statement.
  • Hello World: A Hello World application.
  • Indexers Part I: Shows how C# classes can declare indexers to provide array-like access to objects.
  • Indexers Part II: Shows how to implement a class that uses indexed properties. Indexed properties enable you to use a class that represents an array-like collection.
  • Libraries: Shows how to use compiler options to create a DLL from multiple source files; also, how to use the library in other programs
  • Named and Optional (C# 4.0): Demonstrates Named and Optional parameters, an alternative to method overloads
  • Nullable: Demonstrates value types, such as double and bool, that can be set to null
  • Office Sample (C# 4.0): Demonstrates how Dynamic and COM Interop make it easy to call Microsoft Office in C# 4.0
  • OLEDB: Demonstrates how to use a Microsoft Access database from C# by creating a dataset and adding tables to it.
  • Operator Overloading: Shows how user-defined classes can overload operators
  • Partial Types: Demonstrates how classes and structures can be defined in multiple C# source-code files
  • PInvokeShows how to call exported DLL functions from C#
  • Properties: Shows how properties are declared and used; also demonstrates abstract properties
  • Python Sample (C# 4.0): Learn how to call a Python script by using the Dynamic feature in C# 4.0
  • Security: Discusses .NET Framework security and shows two ways to modify security permissions in C#: using permission classes and permission attributes
  • Simple Variance (C# 4.0): See how Covariance and Contravariance are supported in generic interfaces and delegates
  • Structs: Shows how to use structs in C#.
  • Threading: Demonstrates various thread activities such as creating and executing a thread, synchronizing threads, interacting between threads, and using a thread pool
  • Unsafe: Shows how to use unmanaged code (code that uses pointers) in C#
  • User Conversions: Shows how to define conversions to and from user-defined types
  • Versioning: Demonstrates versioning in C# by using the override and new keywords
  • XML Documents: Shows how to document code by using XML
  • Yield: Demonstrates how to use the yield keyword to filter items in a collection

LinqSamples

These samples help you learn LINQ quickly. They also act as a reference and guide for those with existing LINQ experience. A few handy utilities are also included. They are available in the LinqSamples folder.

  • DynamicQuery: Code to create LINQ queries at run time.
  • LinqToNorthwind: A basic example of how to use LINQ To SQL to query a database
  • LinqToXmlDataBinding: Bind LINQ to XML code to WPF controls
  • ObjectDumper: A utility for writing the output from a LINQ query to the screen in text mode
  • PasteXmlAsLinq: A Visual Studio addin that automatically converts XML to LINQ to XML.
  • QueryVisualizer: Allows LINQ to SQL developers to see the SQL for their query, and also to see the results of the query in a grid.
  • Reflector: Use LINQ to right queries against the objects in your code using the Reflection APIs
  • RSS: This sample acts as a tiny web server that aggregates several RSS feeds
  • SampleQueries: This is the most important sample and contains about 500 examples of how to use each of the query operators in LINQ to Objects, LINQ to SQL, LINQ to XML and LINQ to DataSet.
  • SimpleLambdas: Several examples of how to write and use lambda expressions
  • SimpleLinqToObjects: The hello world of the LINQ samples. This shows you how easy it is to do simple queries of in-memory objects using LINQ to Objects.
  • SimpleLinqToXml: Get started using LINQ to XML.
  • WebServiceLinqProvider(TerraService): A custom LINQ provider and client for the TerraServer-USA Web service.
  • Whitepapers: The following papers are stored in this directory in Word format:
    • LINQ Project Overview
    • LINQ to SQL Overview for C# and VB
    • Standard Query Operators
    • LINQ to XML Overview
  • WinFormsDataBinding: Learn how to display LINQ queries with grids in a Windows form. It includes a one to many query example.
  • XQuery: Another simple LINQ to XML sample query. This sample shows the minimal code necessary to write a LINQ to XML query

Windows mouse acting like a Mac mouse

One great feature about the Mac is the way the mouse movement is active on a window without the need to click on the window.  This is called XWindows mode.

Well I have just found out you can do this in Windows too:

To turn this setting on, just type “mouse works” into the search box in the Control Panel, and you should see an item called “Change how your mouse works”.

In this screen, scroll down and find the checkbox for “Activate a window by hovering over it with the mouse”.

Now life becomes easier.

ASP.NET MVC Routing checker

I came across this nice little MVC routing checker by Phil Haacket

http://haacked.com/archive/2008/03/13/url-routing-debugger/

Simple to use just add

RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

in to the Application_Start of your Global.asax and it does all the reporting on all your Routings

RouteDebug-Binary.zip (4.80 kb)

RouteTesterDemo.zip (16.81 kb)

ASP.NET MVC 3 Internationalization

With MVC getting more popular each day and C# increasing the market share (Tiobe index) and your applications getting larger it is worth looking in to how to Internationalise your application, the source of all sources for internationalization is Guy Smith-Ferrier and his blog is a source of wealthy knowledge.

It’s well worth taking a look at How To Achieve World(-Ready) Domination In ASP.NET MVC 4 by Guy Smith-Ferrier

I came across this useful post for MVC and Internationalization by Nadeem Afana’s, the original post can be found here

Introduction

If your website targets users from different parts of the world, these users might like to see your website content in their own language. Creating a multilingual website is not an easy task, but it will certainly allow your site to reach more audience. Fortunately, the .NET Framework already has components that support different languages and cultures.

We will build an ASP.NET MVC 3 web application that contains the following features:

  • It can display contents in different languages.
  • It autodetects the language from the user’s browser.
  • It allows the user to override the language of their browser.

Globalization and Localization in ASP.NET

Internationalization involves Globalization and Localization. Globalization is the process of designing applications that support different cultures. Localization is the process of customizing an application for a given culture.

The format for the culture name is “<languagecode2>-<country/regioncode2>”, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. Examples include es-CL for Spanish (Chile) and en-US for English (United States).

ASP.NET keeps track of two culture values, the Culture and UICulture. The culture value determines the results of culture-dependent functions, such as the date, number, and currency formatting. The UICulture determines which resources are to be loaded for the page by the ResourceManager. The ResourceManager simply looks up culture-specific resources that is determined by CurrentUICulture. Every thread in .NET has CurrentCulture and CurrentUICulture objects. So ASP.NET inspects these values when rendering culture-dependent functions. For example, if current thread’s culture (CurrentCulture) is set to “en-US” (English, United States), DateTime.Now.ToLongDateString() shows “Saturday, January 08, 2011”, but if CurrentCulture is set to “es-CL” (Spanish, Chile) the result will be “sábado, 08 de enero de 2011”.

How to Support Different Languages in ASP.NET MVC 3

There are two ways to incorporate different languages and cultures in ASP.NET MVC 3:

  1. By using resource strings in all our site views. (See part 2)
  2. By using different set of views for every language and locale.
  3. By mixing between 1 and 2

Which one is the best?
It depends on you. It is a matter of convenience. Some people prefer to use a single view for all languages because it is more maintainable. While others think replacing views content with code like “@Resources.Something” might clutter the views and will become unreadable. Recall that views have to be as simple as possible. If your views look fine with a lot of inline code, it’s fine. But sometimes you have no choice in languages where layout has to be different like right-to-left languages. Perhaps, a mix of the two is the best. Anyway, in this example we will use the 2nd approach just to show a different way than the usual resource strings.

Views Naming Conventions

In order to create different views for every culture, we will append the culture name to the name of the view. For example, Index.cshtml (the default view), Index.es-CL.cshtml (Spanish, Chile), Index.ar-JO.cshtml (Arabic, Jordan). The view name that has no ending is considered the default culture. A default culture view will be rendered if the requested culture name is not implemented explicitly.

Globalizing our Web Site

We will create a new ASP.NET MVC 3 web application and globalize it step by step.

Click “File->New Project” menu command within Visual Studio to create a new ASP.NET MVC 3 Project. We’ll create a new project using the “Internet Application” template.

Creating the Model

We’ll need a model to create our web application. Add a class named “User” to the “Models” folder:

Internationalizing Validation Messages

Our model presented above contains no validation logic, and this is not the case in normal applications nowadays. We can use data annotation attributes to add some validation logic to our model. However, in order to globalize validation messages, we need to specify a few extra parameters. The “ErrorMessageResourceType” indicates the type of resource to look up the error message. “ErrorMessageResourceName” indicates the resource name to lookup the error message. Resource manager will pick the correct resource file based on the current culture.

Now modify the “Person” class and add the following attributes:

namespace MvcInternationalization.Models
{
    public class Person
    {
        [Required(ErrorMessageResourceType=typeof(MyResources.Resources), 
                  ErrorMessageResourceName="FirstNameRequired")]
        [StringLength(50, ErrorMessageResourceType = typeof(MyResources.Resources), 
                          ErrorMessageResourceName = "FirstNameLong")]       
        public string FirstName { get; set; }

        [Required(ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "LastNameRequired")]
        [StringLength(50, ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "LastNameLong")]
        public string LastName { get; set; }

        [Required(ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "AgeRequired")]        
        [Range(0, 130, ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "AgeRange")]                
        public int Age { get; set; }

        [Required(ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "EmailRequired")]
        [RegularExpression(".+@.+\\..+", ErrorMessageResourceType = typeof(MyResources.Resources), 
            ErrorMessageResourceName = "EmailInvalid")]        
        public string Email { get; set; }

        public string Biography { get; set; }
    }
}

Localizing Data Annotations Validation Messages

Because we need to perform data validation on our model using Data Annotations, we will have to add translated resource strings for every culture our site will support. In this case, English, Spanish, and Arabic.

We will store resource files in a separate assembly, so we can reference them in other project types in the future.

Right click on the Solution and then choose the “Add->New Project” context menu command. Choose “Class Library” project type and name it “MyResources”.

Now right click on “MyResources” project and then choose “Add->New Item” context menu command. Choose “Resource File” and name it “Resources.resx”. This will be our default culture (en-US) since it has no special endings. Add the following names and values to the file like below:

Remember to mark the resource’s access modifier property to “public”, so it will be accessible from other projects.

Now create a new resource file and name it “Resources.es-CL.resx” and add the following names and values like below:

Now, do the same for the Arabic version. You may not be able to enter the correct strings by keyboard because your OS may not be configured to accept Arabic. However, you can download the files from the link at the top. Anyway, the resource file is included for reference:

We need to reference “MyResources” project from our web application, so that we can read the resource strings right from our web site. Right click on “References” under our web project “MvcInternationalization”, and choose the “MyResources” project from Projects tab.

Determining Culture

How do we determine which version of a view to return to the end user?
How do we know which culture does the user want?

There is a header field called “Accept-Language” that the browser sends on every request. This field contains a list of culture names (language-country) that the user has configured in their browser. The problem is that this culture may not reflect the real user’s preferred language, such as a computer in a cybercafé. We should allow the user to choose a language explicitly and allow them even to change it. In order to do this sort of things, we need to store the user’s preferred language in a store, which can be perfectly a cookie.

We will create a base controller that inspects the cookie contents first, if there is no cookie, we will use the “Accept-Language” field sent by their browser. Create a controller and name it “BaseController” like below:

namespace MvcInternationalization.Controllers
{
    public class BaseController : Controller
    {
        
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // Is it View ?
            ViewResultBase view = filterContext.Result as ViewResultBase;
            if (view == null) // if not exit
                return;

            string cultureName = Thread.CurrentThread.CurrentCulture.Name; // e.g. "en-US" // filterContext.HttpContext.Request.UserLanguages[0]; // needs validation return "en-us" as default 

            // Is it default culture? exit
            if (cultureName == CultureHelper.GetDefaultCulture())
                return;

            
            // Are views implemented separately for this culture? if not exit
            bool viewImplemented = CultureHelper.IsViewSeparate(cultureName);
            if (viewImplemented == false)
                return;
            
            string viewName = view.ViewName;

            int i = 0;

            if (string.IsNullOrEmpty(viewName))
                viewName = filterContext.RouteData.Values["action"] + "." + cultureName; // Index.en-US
            else if ((i = viewName.IndexOf('.')) > 0)
            {
                // contains . like "Index.cshtml" 
                viewName = viewName.Substring(0, i + 1) + cultureName + viewName.Substring(i);
            }
            else
                viewName += "." + cultureName; // e.g. "Index" ==> "Index.en-Us"

            view.ViewName = viewName;

            filterContext.Controller.ViewBag._culture = "." + cultureName;

            base.OnActionExecuted(filterContext);
        }


        protected override void ExecuteCore()
        {
            string cultureName = null;
            // Attempt to read the culture cookie from Request
            HttpCookie cultureCookie = Request.Cookies["_culture"];
            if (cultureCookie != null)
                cultureName = cultureCookie.Value;
            else
                cultureName = Request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages

            // Validate culture name
            cultureName = CultureHelper.GetValidCulture(cultureName); // This is safe



            // Modify current thread's culture 
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName);
            
            
            base.ExecuteCore();
        }



    }
}

The base controller checks if the cookie exists, and sets the current thread culture to that cookie value. Of course, because cookie content can be manipulated on the client side, we should always validate its value using a helper class called “CultureHelper”. If the culture name is not valid, the helper class returns the default culture. After that, when we call “Return” in controller action methods, the view name is modified by the base controller behind the scenes to reflect the correct culture in cookie or header field. This way we make sure that the user gets the right content based on their culture.

CultureHelper Class

The CultureHelper is basically a utility that allows us to store culture names we are implementing in our site:

namespace MvcInternationalization.Utility
{
    public static class CultureHelper
    {
        // Include ONLY cultures you are implementing as views
        private static readonly  Dictionary<String, bool> _cultures  = new Dictionary<string,bool> {
            {"en-US", true},  // first culture is the DEFAULT
            {"es-CL", true},
            {"ar-JO", true}
        };


        /// <summary>
        /// Returns a valid culture name based on "name" parameter. If "name" is not valid, it returns the default culture "en-US"
        /// </summary>
        /// <param name="name">Culture's name (e.g. en-US)</param>
        public static string GetValidCulture(string name)
        {
            if (string.IsNullOrEmpty(name))
                return GetDefaultCulture(); // return Default culture

            if (_cultures.ContainsKey(name))
                return name;

            // Find a close match. For example, if you have "en-US" defined and the user requests "en-GB", 
            // the function will return closes match that is "en-US" because at least the language is the same (ie English) 
            foreach(var c in _cultures.Keys)
                if (c.StartsWith(name.Substring(0, 2)))
                    return c;

            
            // else 
            return GetDefaultCulture(); // return Default culture as no match found
        }


        /// <summary>
        /// Returns default culture name which is the first name decalared (e.g. en-US)
        /// </summary>
        /// <returns></returns>
        public static string GetDefaultCulture()
        {
            return _cultures.Keys.ElementAt(0); // return Default culture

        }


        /// <summary>
        /// Returns "true" if view is implemented separatley, and "false" if not.
        /// For example, if "es-CL" is true, then separate views must exist e.g. Index.es-cl.cshtml, About.es-cl.cshtml
        /// </summary>
        /// <param name="name">Culture's name</param>
        /// <returns></returns>
        public static bool IsViewSeparate(string name)
        {
            return _cultures[name];
        }

    }
}

We should populate “_cultures” manually. The “_cultures” dictionary stores the list of culture names our site supports. The first parameter indicates culture name (e.g. en-US), the second parameter indicates whether we are implementing separate views for that culture. If the second parameter is false, the default view is used (ie the one that has no special ending).

The nice part of this utility class is that it serves similar languages. For example, if a user is visiting our site from Argentina (es-ar), a culture which is not implemented in our site, he or she will see our site in Spanish using “es-cl” (Spanish, Chile) instead of English language. This way, you don’t have to implement all cultures unless you really care about currency, date format, etc.

Controllers

Visual Studio has created a controller named “HomeCotnroller” for us, so we’ll use it for simplicity. Modify the “HomeController.cs” so that it looks like below:

namespace MvcInternationalization.Controllers
{
    public class HomeController : BaseController
    {
        [HttpGet]
        public ActionResult Index()
        {
          
            return View();
        }

        [HttpPost]
        public ActionResult Index(Person per)
        {
                 return View();
        }

        public ActionResult SetCulture(string culture)
        {
            // Validate input
            culture = CultureHelper.GetValidCulture(culture);

            // Save culture in a cookie
            HttpCookie cookie = Request.Cookies["_culture"];
            if (cookie != null)
                cookie.Value = culture;   // update cookie value
            else
            {

                cookie = new HttpCookie("_culture");
                cookie.HttpOnly = false; // Not accessible by JS.
                cookie.Value = culture;
                cookie.Expires = DateTime.Now.AddYears(1);
            }
            Response.Cookies.Add(cookie);

            return RedirectToAction("Index");
        }

        public ActionResult About()
        {
            
           return View();
        }

        



    }
}

The “SetCulture” action allows the user to change their current culture and stores it in a cookie called “_culture”. We are not restricted to cookies, we could instead save the culture name in Session or elsewhere, but cookies are really lightweight since they do not take any type of space on server side.

Creating a View Template

Now we will implement the View associated with the HomeController’s Index action. First delete the existing Index.cshtml file under “Views/Home” folder. Now to implement the view right-click within the “HomeController.Index()” method and select the “Add View” command to create a view template for our home page:

We will need to modify some of the settings above. Choose the option “Create a strongly-typed view” and choose the “Person” class we created before. Also, choose the “Create” menu item from the “Scaffold template” drop-down box.

When we click the “Add” button, a view template of our “Create” view (which renders the form) is created. Modify it so it looks like below:

The javascript code simply post back the form to set the culture. The “selected” helper is used to mark the appropriate culture radio button as checked.

Now make two copies of “Index.cshtml” and rename them to “Index.es-CL.cshtml” and “Index.ar-JO.cshtml”. These latter views represent the localized versions of Index.cshtml for two different cultures, so we can add whatever is necessary inside them. Make them look like below:


Spanish view


Arabic view

Of course, for simple partial views like “_LogOnPartial.cshtml” and which are not referenced by controllers, we can use resource strings perfectly.


Arabic view

Try It Out

Run the website now. Notice that client side validation is working nicely. Click on radio buttons to switch between cultures, and notice how right-to-left language is showing correctly. Using separate views allowed us to control how to position elements, and have made our views clean and readable.


English


Spanish


Arabic

Client-Side localization

What about client-side scripts?

For client-side, we should worry mainly about numbers, date and time, and messages since these change from culture to culture. There are many ways to implement client-side localization. But here are two common options:

  1. Creating standalone localized javascript files for every culture and language.
  2. Creating a standard common javascript file for all cultures by sticking to Microsoft Ajax Library.

For (1), we follow the same convention for views and resource files. For example, for the file “myscript.js”, you need to create “myscript.es-CL.js”, “myscript.ar-JO.js”, etc. We can reference the javascript files easily from our views by appending culture name to the javascript file :

<script src="@Url.Content("~/Scripts/myscript" + ViewBag._culture + ".js")" type="text/javascript"></script>

The variable “_culture” is already defined in the base controller and works nicely by ignoring default culture (returns null in this case).

Even if you want to use Microsoft Ajax Library, you may still need separate javascript files that define text messages to the end user. You can define a literal object that contains the list of messages, or if you are using separate views for every culture, you can use inline javascript instead of separate javascript files.

Summary

Building a multilingual web application is not an easy task. but it’s worth it especially for web applications targeting users from all over the world, something which many sites do. It is true that globalization is not the first priority in site development process, however, it should be well planned early in the stage of development so it can be easily implemented in the future. Luckily, ASP.NET supports globalization and there are plenty of .NET classes that are handy. We have seen how to create an ASP.NET MVC 3 application that supports 3 different languages, including a right-to-left one, which requires a different UI layout. Anyway, here is a summary of how to globalize a site in ASP.NET MVC 3:

  1. Add a base controller from which all controllers inherit. This controller will intercept the view names returned and will adjust them depending on the current culture set.
  2. Add a helper class that stores the list of culture names that the site will support.
  3. Create a single view or set of views for every culture and language.
  4. Create resource files that contain translation of all string messages. (e.g. Resources.resx, Resources.es-CL.resx, Resources.ar-JO.resx, etc )
  5. Localize javascript files.

Workflow with TFS

I’ve been working with TFS for sometime and when you are using the process flows you need to understand how the workflows work with the work items types.

There are two main types I have worked with Agile and CMMI Process Improvements.

I’m not an expert on these workflows but you can get access to the full guidance from:

The diagrams below are taken from VSTS blog site, but you must remember thes eare just starting points and they can be changed to suit your own workflow within your business

MSF for Agile Software Development

featuring 5 work item types: Bug, Requirement, Quality of Service Requirement (QoS), Risk and Task.

Work Item Type: Bug

 

Work Item Type: Scenario


 

Work Item Type: Quality of Service Requirement (also known as “technical requirement”)

 

Work Item Type: Risk

 

Work Item Type: Task

 

MSF for CMMI Process Improvement

featuring 7 work item types: Bug, Requirement, Change Request, Issue, Review, Risk, Task

Work Item Type: Bug

 

Work Item Type: Requirement

 

Work Item Type: Change Request

 

Work Item Type: Issue

 

Work Item Type: Review

 

Work Item Type: Risk

 

Work Item Type: Task

Amending a SQL table without getting “Saving changes is not permitted”

When I come to amend a table in SQL Server all is fine until you come to save the new structure you end up getting the following message:

“Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can’t be re-created or enabled the option Prevent saving changes that require the table to be re-created.”

This is happening because ““Prevent saving changes that require table re-creation” option is enabled.  You can disable this by going into Tools -> Options -> Designers-> Uncheck “Prevent saving changes that require table re-creation”, this is either in Visual Studio or SQL Management Studio.

Now you can apply your new changes to the table