Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Dot Net Rules

Yes, to dance beneath the diamond sky with one hand waving free

Ιστορικό Δημοσιεύσεων

Ιανουάριος 2013 - Δημοσιεύσεις

Creating tooltips using JQuery

I have been using JQuery for a couple of years now and it has helped me to solve many problems on the client side of web development.

You can find all my posts about JQuery in this link. In this post I will be providing you with a hands-on example on how to create a stylish tooltip using JQuery.

In this hands-on example I will be using Expression Web 4.0.This application is not a free application. You can use any HTML editor you like.You can use Visual Studio 2012 Express edition. You can download it here. 

We need to download the latest version of JQuery. You can download it here.

We will need some markup first.This is the sample HTML 5 page

Type or (copy paste) the markup in your favorite HTML editor (VS, Expression Web,Notepad++)

 

<!DOCTYPE html>
<html lang="en">

  <head>
    <title>Liverpool Legends</title>
    <script type="text/javascript" src="jquery-1.8.3.min.js"></script>
    <link rel="stylesheet" type="text/css" href="mystyle.css">
     <script type="text/javascript" src="tooltip.js"></script>

       
</head>

  <body>
    <header>
   
   
        <h1>Liverpool Legends</h1>

    </header>
   
    <div id="main">
   
 
     <a class="liverpool" href="http://en.wikipedia.org/wiki/John_Barnes_%28footballer%29" target="_blank" Tooltip="One of the greatest midfielders to wear the Liverpool shirt">John Barnes</a>
<br/>
<a class="liverpool" href="http://en.wikipedia.org/wiki/Kenny_Dalglish" target="_blank" Tooltip="The greatest ever player that has played for Liverpool">Kenny Dalglish</a>
<br/>
<a class="liverpool" href="http://en.wikipedia.org/wiki/Steven_Gerrard" target="_blank" Tooltip="A liverpool legend and the captain of the team">Steven Gerrard</a>
     
    </div>
   
   
    <footer>
   
    <p>All Rights Reserved</p>
 
    </footer>

  
  </body>
 
</html>

I have some links in this simple html page. When I hover over the links I want the the contents of the Tooltip attribute to appear on the right of the links as a tooltip. When I mouse out of the links then the tooltip contents should disappear.

I am including a link to the JQuery library in the head section of the HTML markup.

I will also include the external .css stylesheet file with the various styles for the HTML elements in the head section.

You must create another file first e.g mystyle.css and copy-paste in it the code below

body
{
background-color:#efefef;

}

header

{

font-family:Tahoma;
font-size:1.3em;
color:#505050;
text-align:center;
}

a:link {color:#64000; text-decoration:none;}   

a:hover {color:#FF704D; text-decoration:none;}  


.tooltip {
    display: none;
    font-size: 12pt;
    position: absolute;
    border: 2px solid #000000;
    background-color: #b13c3c;
    padding: 12px 16px;
    color: #fff347;
}
   
    footer
{
background-color:#999;
width:100%;
text-align:center;
font-size:1.1em;
color:#002233;
}
 

Have a look at the class tooltip above.

I have also included a link to the external .js javascript script (tooltip.js) file with the various styles for the HTML elements in the head section.

Type (copy-paste the following) javascript code in the tooltip.js

$(function() {
    $('.liverpool').hover(function(event) {
        var toolTipcontents = $(this).attr('Tooltip');
        $('<p class="tooltip"></p>').text(toolTipcontents)
            .appendTo('#main')
            .css('top', (event.pageY - 40) + 'px')
            .css('left', (event.pageX + 60) + 'px')
            .fadeIn(4000);
    }, function() {
        $('.tooltip').remove();

    }).mousemove(function(event) {
        $('.tooltip')
        .css('top', (event.pageY - 40) + 'px')
        .css('left', (event.pageX + 60) + 'px');
    });
   
     });


Let me explain what I am doing with the code above.

  • First I make sure that DOM has loaded before I do anything else.
  • Then in the hover over event, I store in the variable toolTipcontents the contents of the Tooltip attribute.Have a look here for the attr() function.
  • Then I create a p tag dynamically and assign the contents of the toolTipcontents variable to it.Have a look here for the text() function.
  • Then I simply append this p tag to the main div of the page and then set the position (top,left) that the tooltip will appear.Have a look here for the appendTo() function. Also have a look here for the css() function.
  • Then I use an effect to make the tooltip contents appear with a simple fading. .Have a look here for the fadeIn() function.
  • Then in the hover out event I simply remove the p tag.Have a look here for the remove() function.
  • Finally because I want the tooltip contents to move along as the mouse moves I add some code to the mousemove() event. Have a look here for the mousemove() event.


Make sure you view your page in you browser of preference.

Have a look at the picture below to see what I see when I view this page on the browser and hover over a link.

 

Hope it helps !!!

Posted: Κυριακή, 27 Ιανουαρίου 2013 1:03 πμ από nikolaosk | 0 σχόλια
Δημοσίευση στην κατηγορία: , , ,
Looking into the various ways that content can be shared in a DotNetNuke site

In this post I will demonstrate with a hands-on example the various ways content can be shared across many pages in a DotNetNuke site.

I will continue writing posts about DotNetNuke because it is my favourite CMS,based on ASP.Net and I use it a lot. 

I have installed DNN 7.0 in a web server. You can see the default installation and site -http://dnn7.nopservices.com/

Bear in mind that this is the community edition of DotNetNuke

1) I am logging into my site as a host - power user.

2) I am going to add a Text/HTML module to the Home.aspx page.

3) I am navigating to Modules -> Add New Module. From the available modules I choose HTML module.This is the most commonly used module in DNN sites. We can add content, images, flash files into this module.

4) I am adding this module to the ContentPane of the Home page

Have a look at the picture below

 

5) Now, that I have the module in my pane, I must add some content to it.I just click on the Edit Content

Have a look at the picture below

 

6) I add some sample content (inside the HTML editor) on the page and click Save.My content has been added.

Have a look at the picture below

 

7) Now what if I wanted to share the contents of the the Text/HTML module across other pages of the site?

I navigate to the http://dnn7.nopservices.com/AboutUs.aspx page,then Modules -> Add Existing module. Then I select the Home page, the Text/HTML module I added in the Home page (I have titled it DNN) and then I add it in the new page (AboutUs) in the ContentPane

Have a look at the picture below

 

8) The module and its contents are inserted in the AboutUs page. Have a look at the picture below

 

 9) Now if I go back to the Home page and I add some more content.Have a look at the picture below

I have added "The main site where you can download everything is http://www.dotnetnuke.com". If you navigate to the AboutUs page you will see that those changes were reflected to that page as well.

10) But what if I did not want this to happen? I mean what if we wanted to copy a module across one or more pages but didn't want to have the content changes of one module reflected to the others in the other pages.

First I am going to delete the Text/HTML module (titled DNN) from the AboutUs page.

Have a look at the picture below

 

11) Now I am going to add the Text/HTML module (titled DNN) from the Home page to the AboutUs page again.I navigate to the http://dnn7.nopservices.com/AboutUs.aspx page,then Modules -> Add Existing module. Then I select the Home page, the Text/HTML module I added in the Home page (I have titled it DNN) and then I add it in the new page (AboutUs) in the ContentPane.Please note that I have checked the option Make a Copy

Have a look at the picture below

 

The Text/HTML module is added to this page as well. Now if I navigate to the Home page and add another line of content in the Text/HTML module e.g

You can download the latest version of DotNetnuke and very useful manuals.

and then move back to the AboutUs page, we will see that this new change did not reflect on the AboutUs page.

12) Finally I would like to show you another way to share content across multiple pages in a DNN site.

I am adding a new module to the Home page.  I am navigating to Modules -> Add New Module from the control panel. From the available modules I choose HTML module.I add some sample content to this module. You can add anything you like. I have titled this module DNN RoadMap by going to the module Settings.

Have a look at the picture below

 

Then I add the module title and in Advanced Settings, I check the option Display Module on All Pages. By doing that this module will appear in the same position in all pages of the site.

I have the option to add this module only to the pages ( Add to new pages only? ) that will be created in the future (new pages) but I will not do that right now.

Then I hit the Update button. This module will be added to all pages.

Have a look at the picture below.

 

Please note that by using this setting we have the following behavior

  •  If you change the contents of the module titled DNN RoadMap that was added to all pages, those changes will be reflected across the site.
  •  If you delete the module from one page, that does not mean that all modules from all the pages will be deleted. 
  •  If you go to any page that the module DNN RoadMap was added and then go to Settings and then uncheck the option Display Module On All Pages , then this module will disappear from all the pages except the current one.

Hope it helps!!!

Removing DotNetNuke copyright message from a DNN site

I have been using ASP.Net extensively to build web applications based on the .Net Framework. In this blog I have been demonstrating with hands-on examples how to use ASP.Net Web Forms and ASP.Net MVC to implement functionality commonly found on ASP.Net web sites.

I have also used DotNetNuke - DNN (the Open Source Web Application Framework of my choice) to build websites.I am also the co-admin of the greek DotNetNuke community and I decided that I will use this space to write a series of posts regarding DotNetNuke. I have decided to keep those posts short. I will provide tips and tricks and answers to questions I often get when I teach about DotNetNuke in open seminars.

I would like to introduce DotNetNuke to you before I move on.DotNetNuke is an Open Source Web Application Framework that is based on ASP.Net.


It is ideal for creating and deploying projects such as:

  • Commercial Web Sites
  • Corporate Intranets and Extranets
  • Online Publishing Portals
  • Other Web Applications

There are 3 DNN editions.DotNetNuke Professional edition,DotNetNuke Enterprise edition and DotNetNuke Community edition. Have a look at a comparison of the various editions here.

I will be using the community edition in all my posts.

In this short post I will show you how to remove the DotNetNuke copyright message from the View source (View -> Page Source) of your DNN site.

Before I move on I must have a working installation of DNN.

I have installed DNN 7.0 in a web server. You can see the default installation and site - http://dnn7.nopservices.com/

In another post of mine I will demonstrate how to install DotNetNuke 7.0 in your machine or a live web server.

Let's move on with our actual example.

When I view my website - http://dnn7.nopservices.com/ on the browser and right-click on the page (View --> Page Source) I see the following message.

Have a look at the picture below


 

One question I often get is how to remove that copyright message and the keywords (which certainly will be irrelevant with the keywords we want to add for our specific site)

We login as superuser to our DNN site and then choose Host->Host Settings

Have a look at the picture below

 

Then I choose Basic Settings, then Appearance.

There is a setting - Show Copyright Credits? - which is checked. We must uncheck this option and click Update.

Have a look at the picture below

 

When I view my website again and then right-click on the page (View --> Page Source) , I do not see either the DNN copyright message or the keywords which were specific to DNN.

Have a look at the picture below

 

Please note that you can follow these steps for your DNN 6.0 website.

Hope it helps

Posted: Κυριακή, 20 Ιανουαρίου 2013 8:54 μμ από nikolaosk | 0 σχόλια
Δημοσίευση στην κατηγορία: , , ,
Looking into the ASP.Net Web API - part 2

This is the second post discussing the ASP.Net Web API. I will continue building a small ASP.Net MVC 4.0 application that I started implementing in my last post.

You can have a look at the first post here. In this hands-on example I will show you how to create new footballer items,update a new footballer item,delete a new footballer item.

I will also refactor the implementation for the GET operations-methods from my last post.I will present you with a full CRUD hands-on example. This will be based in the RESTful WEB API paradigm and its four main HTTP methods. GET will retrieve the footballer items from the specified URI.PUT updates a resource (footballer item) at a specified URI.POST will create a new resource (footballer item).DELETE will delete a resource (footballer item) at a specified URI.

Let's move on to actually building the application.

1) Launch Visual Studio , I have named my application "WebApi", and open the application.

2) As I said earlier I will refactor the code I created in the first post.

 Inside the Models folder my class file Footballer.cs looks exactly the same.

 

     public class Footballer
    {
        public int FootballerID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public double Weight { get; set; }
        public double Height { get; set; }
        public DateTime JoinedClub { get; set; }
        public string PositionPlayed { get; set; }
        public int GoalsScored { get; set; }


    } 

 

I need to create a collection of objects - footballer objects.I will use the Repository Pattern to separate the collection of objects  from our service implementation.

In Solution Explorer, right-click the Models folder. Select Add, then select New Item. From the available Templates pane, select Installed Templates. Under C#, select Code. In the list of code templates, select Interface. Name the interface IFooballerRepository.cs.

The code for the interface implementation follows

public interface IFootballerRepository
    {
        IEnumerable<Footballer> GetPlayers();
        Footballer GetFooballerById(int id);
        Footballer AddFootballer(Footballer item);
        void RemoveFootballer(int id);
        bool UpdateFootballer(Footballer item);
    }

 

3) Now, we obviously need to implement this interface. We need to add another class to the Models folder, named FootballerRepository.cs. This class will implement the IFootballerRepository interface. Add the following implementation:

   

 public class FootballerRepository :IFootballerRepository

    {

       private List<Footballer> footballers = new List<Footballer>();

         private int _nextId = 1;


        public FootballerRepository()
        {

   

            footballers.Add(new Footballer { FootballerID = 1, FirstName = "Steven", LastName = "Gerrard", Height = 1.85, Weight = 85, JoinedClub = DateTime.Parse("12/12/1999"), PositionPlayed = "Attacking Midfielder", GoalsScored = 23 });

            footballers.Add(new Footballer { FootballerID = 2, FirstName = "Jamie", LastName = "Garragher", Height = 1.89, Weight = 89, JoinedClub = DateTime.Parse("12/02/2000"), PositionPlayed = "Central Defender", GoalsScored = 2 });

            footballers.Add(new Footballer { FootballerID = 3, FirstName = "Luis", LastName = "Suarez", Height = 1.72, Weight = 73, JoinedClub = DateTime.Parse("12/01/2012"), PositionPlayed = "Striker", GoalsScored = 27 });

        }

     

        public IEnumerable<Footballer> GetPlayers()
        {
            return footballers;
        }


        public Footballer GetFooballerById(int id)
        {

            return footballers.Find(f => f.FootballerID == id);
        }

 


    public Footballer AddFootballer(Footballer item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.FootballerID = _nextId++;
            footballers.Add(item);
            return item;
        }



        public void RemoveFootballer(int id)
        {
            footballers.RemoveAll(f => f.FootballerID == id);
        }

 

        public bool UpdateFootballer(Footballer item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            int index = footballers.FindIndex(f => f.FootballerID == item.FootballerID);
            if (index == -1)
            {
                return false;
            }
            footballers.RemoveAt(index);
            footballers.Add(item);
            return true;
        }
    }

 

Let me explain the implementation above.

I create a generic collection of Fooballer objects (footballers)

  private List<Footballer> footballers = new List<Footballer>();
 

Then I populate the list with objects that live in the computer's memory

public FootballerRepository()
        {

    

            footballers.Add(new Footballer { FootballerID = 1, FirstName = "Steven", LastName = "Gerrard", Height = 1.85, Weight = 85, JoinedClub = DateTime.Parse("12/12/1999"), PositionPlayed = "Attacking Midfielder", GoalsScored = 23 });

            footballers.Add(new Footballer { FootballerID = 2, FirstName = "Jamie", LastName = "Garragher", Height = 1.89, Weight = 89, JoinedClub = DateTime.Parse("12/02/2000"), PositionPlayed = "Central Defender", GoalsScored = 2 });

            footballers.Add(new Footballer { FootballerID = 3, FirstName = "Luis", LastName = "Suarez", Height = 1.72, Weight = 73, JoinedClub = DateTime.Parse("12/01/2012"), PositionPlayed = "Striker", GoalsScored = 27 });

        }
 

 Well, I trust you have some knowledge of C# and collection initializers which is a C# 3.0 feature. Have a look here if you want to learn more about it.The individual object initializers are enclosed in braces and separated by commas.

Next, I implement two simple methods. GetPlayers() returns a list of players.GetFooballerById(int id) returns a single footballer by its ID.

 public IEnumerable<Footballer> GetPlayers()
        {
            return footballers;
        }


        public Footballer GetFooballerById(int id)
        {

            return footballers.Find(f => f.FootballerID == id);
        }

 Next I am implementing the AddFootballer method which is pretty straightforward method. If there is no item-object we throw an exception. If there is an item we give it a new ID and add the object to the collection.

    public Footballer AddFootballer(Footballer item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.FootballerID = _nextId++;
            footballers.Add(item);
            return item;
        }

 

Next I am implementing the RemoveFootballer method.I just remove an object from the collection with a specific id.

      public void RemoveFootballer(int id)
        {
            footballers.RemoveAll(f => f.FootballerID == id);
        }

Finally I implement the UpdateFootballer method.If there is no item-object we throw an exception. Then I find the index of the object in the collection array according to its ID and then remove it and add the new one.

 public bool UpdateFootballer(Footballer item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            int index = footballers.FindIndex(f => f.FootballerID == item.FootballerID);
            if (index == -1)
            {
                return false;
            }
            footballers.RemoveAt(index);
            footballers.Add(item);
            return true;
        }

4) Now we need to change the code we have written for our controller FootballerController.cs in the Controllers folder.

Comment everything inside this class and just leave the code below

    public class FootballerController : ApiController
    {

 

    }  

The complete implementation follows

public class FootballerController : ApiController
    {

        static readonly IFootballerRepository repository = new FootballerRepository();
 
         public IEnumerable<Footballer> GetPlayers()
         {
             return repository.GetPlayers();
         }



        public Footballer GetFooballerById(int id)
        {
            var footballer = repository.GetFooballerById(id);

            if (footballer == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return footballer;
        }

      


        public HttpResponseMessage PostFootballer(Footballer footballer)
        {
            footballer = repository.AddFootballer(footballer);
            var response = Request.CreateResponse<Footballer>(HttpStatusCode.Created, footballer);

            string uri = Url.Link("DefaultApi", new { id = footballer.FootballerID });
            response.Headers.Location = new Uri(uri);
            return response;
        }

        public void PutFootballer(int id, Footballer footballer)
        {
            footballer.FootballerID = id;
            if (!repository.UpdateFootballer(footballer))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public void DeleteFootballer(int id)
        {
            Footballer footballer = repository.GetFooballerById(id);
            if (footballer == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            repository.RemoveFootballer(id);
        }
        
        }

In ASP.NET Web API, a controller is a class that handles HTTP requests from the client.Now I will explain what I have implemented in this class and what methods have been created.

I am adding a field that holds an IFootballerRepository instance.

        static readonly IFootballerRepository repository = new FootballerRepository();


This is the method to get a list of footballers.Well, nothing really to explain here.


         public IEnumerable<Footballer> GetPlayers()
         {
             return repository.GetPlayers();
         }

This is the method to get a footballer item by id.This method name also starts with Get.This method has a parameter named id. This parameter is mapped to the id segment of the URI path.

The method will throw an exception of type HttpResponseException if id is not valid. This exception will be translated by Web API as a 404 (Not Found) error.


        public Footballer GetFooballerById(int id)
        {
            var footballer = repository.GetFooballerById(id);

            if (footballer == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return footballer;
        }


Now I would like to explain again how the ASP.NET Web API  knows how to map URIs to our controller methods. 

The ASP.NET Web API framework for each HTTP message decides which controller receives the request by consulting a route table. The Web API  project contains a default route that you can find in the WebApiConfig.cs file.

/api/{controller}/{id}

The {controller} and {id} are just placeholders.

{controller} is matched to the controller name. {controller} in my case is footballer. 


The HTTP request method is matched to the method name. (This rule applies only to GET, POST, PUT, and DELETE requests.)



/api/footballer will match the  GetPlayers() method


/api/footballer/1 will match the  GetFooballerById(1) method

 

Next I am implementing the PostFootballer method.This will create a new footballer item.The new item is created when the client sends a HTTP POST request to the server with the new footballer object in body of the request message.

     public HttpResponseMessage PostFootballer(Footballer footballer)
        {
            footballer = repository.AddFootballer(footballer);
            var response = Request.CreateResponse<Footballer>(HttpStatusCode.Created, footballer);

            string uri = Url.Link("DefaultApi", new { id = footballer.FootballerID });
            response.Headers.Location = new Uri(uri);
            return response;
        }

The way POST requests are getting handled, we define a method whose name starts with Post. The method takes a parameter of type Footballer. The clients to sends to the server a serialized representation of a footballer object, using either XML or JSON for the serialization.

Next we must think of the response code.The Web API framework sets the response status code to 200 (OK). HTTP/1.1 protocol dictated that when a POST request results in the creation of a resource, the server should reply with status 201 - Created.When the server creates a resource, it should include the URI of the new resource in the Location header of the response. 

Next I am implementing the PutFootballer method.This method will update a footballer item.This method name starts with Put which makes the Web API to match it to PUT requests. The method takes two parameters, the footballer Id and the updated footballer object. The id parameter is taken from the URI path, and the footballer parameter is deserialized from the request body. The ASP.NET Web API framework takes simple parameter types from the route. Complex types are taken from the request body. 

        public void PutFootballer(int id, Footballer footballer)
        {
            footballer.FootballerID = id;
            if (!repository.UpdateFootballer(footballer))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
         }

Next I am implementing the DeleteFootballer method.We define a method whose name starts with Delete so the Web API matches it to DELETE requests.

Τhe method has a parameter named id. This parameter is mapped to the "id" segment of the URI path. Ιf the footballer object is not found an exception is thrown. If the deletion is successful then status code 204 (No Content) will be returned.

        public void DeleteFootballer(int id)
        {
            Footballer footballer = repository.GetFooballerById(id);
            if (footballer == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            repository.RemoveFootballer(id);
        }

In the next and final post in this series I will build the Index.cshtml using Knockout which is a JavaScript library that helps developers to create rich, responsive displays when a clean underlying data model exists.

I think that this is enough material for one post and before I implement Index.cshtml I must introduce Knockout library to you.

Hope it helps!!! 

Looking into the ASP.Net Web API - part 1

In this post I would like to show you a hands on example on ASP.Net Web API by building a small ASP.Net application. I am going to build an ASP.Net MVC 4.0 Web application to create a Web API that returns a list of football players. I will also use the popular Javascript library JQuery to issue requests to the server.In the second part of this blog post I will show you how to support more operations in an HTTP service like create,update,delete players using a REST architectural style.

Before I go on with the actual example I will talk a little bit about REST. In 2000, Roy Fielding introduced REpresentational State Transfer in his P.H.D Thesis.

It describes a scalable architecture for building services that build on HTTP.REST is fundamentally different from SOAP.SOAP defines a transport-neutral model that is focused on defining custom services contracts with custom operations.You can invoke those operations over a variety of different transports using different message encodings.REST defines a transport-specific (HTTP) model focused on resources.

In REST we build services around a uniform interface and common data formats.HTTP methods are GET,POST,PUT,DELETE also known as verbs.Data formats supported in REST inculde HTML,XML,JSON.

REST is also known as a Resource Orientated Architecture.The main focus is on identifying and naming resources (URIs). We also focus on how to represent them (XML Format) .We use uniform interface to interact with those URIs through HTTP verbs (GET,POST,PUT,DELETE ). Through this model we can achieve interoperability and scalability for our applications.

Web API is a fully extensible framework for building HTTP based endpoints on top of ASP.Net.It was released with ASP.Net MVC 4.0. It is based on ASP.Net Routing and but is not linked only to ASP.Net MVC. You can use it in a Web Forms project as well. You can download it through NuGet so you can have the latest version.

The most important thing right now is to download and install all the tools,libary,software in your computer so you can follow along. You can download all the necessary software (tools-Visual Studio 2012 Web Edition along with a web server- , a Sql Server instance, libraries,binaries) if you download Web Platform Installer.You can download this tool from this link.

After you install it, you must search for Visual Studio Express 2012 for Web 

Have a look at the picture below

 

Then click Add and then Install.Everything you need will be installed. Maybe you need to reboot the machine so do not worry if you will have to do this.

I have installed Visual Studio 2012 Ultimate edition in my machine which is Windows 8 by the way. I have also installed the latest version of .Net Framework and I will show you later how to download more libraries when needed.I have installed SQL Server 2012 Enterprise Edition in my machine. As a Microsoft Certified Trainer I have access to this software but as explained earlier you need only to download Web Platform Installer and then download the Visual Studio Express 2012 for Web and install it.

 

Let's start building our ASP.Net MVC 4.0 Web application

1)  I am launching VS 2012 and I will Visual C# as the programming language. I will also select ASP.NET MVC 4 Web Application from the available templates.Have a look at the picture below

 

I have named my application "WebApi" and then clicked OK.

2) From the available templates in the next screen I select Web API. This template will create all the necessary files in order to build the application. Click OK.

Have a look at the picture below.

 

 3) Have a look at the Solution Explorer to get a feeling of the files being created and the structure of the web application. Have a look at the picture below

 

 

 4) Now we need to add a model that will basically be the data in our application. The way everything works is the following

  •  We will pass a request to the server, an HTTP request message to the server, then the server will respond with an HTTP response serializing the model to JSON or XML or any other format.
  • On the client side serialized data can be parsed and deserialized.Most clients can parse XML and JSON.

Have a look at the picture below to see the how I add a new model to my application. I simply add a class file to my model in the Models folder.

 

I name the class Footballer.cs

The code follows

 

public class Footballer
    {
        public int FootballerID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public double Weight { get; set; }
        public double Height { get; set; }
        public DateTime JoinedClub { get; set; }
        public string PositionPlayed {get;set;}

        public int GoalsScored {get;set;}


    } 

 

5) We need to add a new controller that basically will handle the HTTP request. Add a new controller, as follows:

In Solution Explorer, right-click the the Controllers folder. Select Add and then select Controller.

Have a look at the picture below

In the Add Controller wizard, name the controller "FootballerController". In the Template drop-down list, select Empty API Controller. Then click Add.

 

The FootballerController will inherit from the ApiController class and not the Controller class.

I will add the following methods to the class. 

 public class FootballerController : ApiController
    {

        Footballer[] footballers = new Footballer[]
            {
            new Footballer {
                 FootballerID=1,
                FirstName = "Steven",LastName="Gerrard", Height=1.85,
                Weight=85, JoinedClub=DateTime.Parse("12/12/1999"),
                PositionPlayed="Attacking Midfielder",GoalsScored=23},
            
   
            
             new Footballer {
                  FootballerID=2,
                FirstName = "Jamie",LastName="Garragher", Height=1.89,
                Weight=89, JoinedClub=DateTime.Parse("12/02/2000"),
                PositionPlayed="Central Defender",GoalsScored=2},

             new Footballer {
                  FootballerID=3,
                FirstName = "Luis",LastName="Suarez", Height=1.72,
                Weight=73, JoinedClub=DateTime.Parse("12/01/2012"),
                PositionPlayed="Striker",GoalsScored=27},

            };
 
         public IEnumerable<Footballer> GetPlayers()
         {
             return footballers;
         }

        public Footballer GetFooballerById(int id)
        {
            var footballer = footballers.FirstOrDefault((f) => f.FootballerID == id);
            if (footballer == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return footballer;
        }

        public IEnumerable<Footballer> GetFooballersByPosition(string position)
        {
            return footballers.Where(
                (f) => string.Equals(f.PositionPlayed, position,
                    StringComparison.OrdinalIgnoreCase));
        }
         
        }

 

All my data is stored in an array in memory.We have 3 methods that return data and not view inside the controller class.

GetPlayers() returns a list of players.GetFooballerById(int id) returns a single footballer by its ID.GetFooballersByPosition(string position) returns all football players according to their playing position.

Each method on the controller will map to a URI.The client (in this case the web browser) will send an HTTP GET request to the URI.

 6) Build and run you application. The IIS Express will start, and a notification will appear in the bottom corner of the screen showing the port number that it is running under. A random port number will be selected.

You will see the default page. In my case is http://localhost:57865.Now I must invoke the web API, so must use the following URI http://localhost:57865/api/footballer

Have a look below to see what I see when I view the page in Firefox.It is displayed in XML in the browser.

 

7) Now we need to test the other two methods. The first one will return a footballer by ID and the second one will return data based on the player's playing position.

While my application is still running I type in the browser http://localhost:57865/api/footballer/1 and hit enter.

Have a look at the picture below to see the results I get in Firefox


While my application is still running I type in the browser http://localhost:57865/api/footballer?position=Attacking%20Midfielder and hit enter.

Have a look at the picture below to see the results I get in Firefox.

 

 8) I will write a small client application , a javascript client in order to consume the APIs.I will modify the Index.cshtml file in the Views folder.I will not be using Razor in this post. I will only use plain HTML 5 and Javascript

 The contents of the Index.chstml follow

<!DOCTYPE html>
<html lang="en">
<head>
    <title>ASP.NET Web API</title>
    <link href="../../Content/Site.css" rel="stylesheet" />
    <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript">
     
    </script>



    <script type="text/javascript">
        $(document).ready(function () {



            $.getJSON("api/footballer/",
            function (data) {
            
                $.each(data, function (key, val) {

            
                    var str = val.FirstName + " " + val.LastName;

                
                    $('<li/>', { text: str })
                    .appendTo($('#footballers'));
                });
            });
        });
</script>

 

 

</head>
<body id="body" >
    <div class="main">
        <div>
            <h1>All Footballers</h1>
            <ul id="footballers"/>
        </div>
        <div>
            <label for="FootballerId">ID:</label>
            <input type="text" id="FootballerId" size="5"/>
            <input type="button" value="Search" onclick="find();" />
            <p id="footballer" />
        </div>
    </div>
</body>
</html>

 

Let me explain what I am doing here. There is a link to JQuery library at the top of the script.

I have an HTML 5 markup where I will present the footballers eventually.

With the command below I am sending an Ajax request to the server.The getJSON command does that. The response will be an array of JSON objects. When the request successfully completes, (see code below)  

$.each(data, function (key, val) {

            
                    var str = val.FirstName + " " + val.LastName;

                
                    $('<li/>', { text: str })
                    .appendTo($('#footballers'));

$.getJSON("api/footballer/", 

the data will be returned formatted.

 When I build and run the application this is what I get.

 

My application works. I can see what actually is going on behind the scenes if I have the right tool.

Fiddler is a web debugging proxy tool and you can use it to see all useful information the clients and servers exchange.

You can download Fiddler here.

In my case I am mostly interested in the JSON objects returned from the server.

Have a look at the picture below

9) Now I will show you how to find a footballer by id.

The code for the find() method is 

function find() {
            var id = $('#FootballerId').val();


            $.getJSON("api/footballer/" + id,
                function (data) {
                    var str = data.FirstName + " " + data.LastName;
                    $('#footballer').text(str);
                })
            .fail(
                function (jqXHR, textStatus, err) {
                    $('#footballer').text('Error: ' + err);
                });

We make a call to the jQuery getJSON function to send the AJAX request.We use the ID to construct the request URI. The response from this request is a JSON representation of a single Footballer object.

Have a look at the picture below

 

If I  enter an invalid ID in the search box, then  I get back an HTTP error.

Have a look at the picture below

 

Now I need to explain how the ASP.NET Web API  knows how to map URIs to our controller methods.

The ASP.NET Web API framework for each HTTP message decides which controller receives the request by consulting a route table. The Web API  project contains a default route that you can find in the WebApiConfig.cs file.

/api/{controller}/{id}

The {controller} and {id} are just placeholders.

{controller} is matched to the controller name. {controller} in my case is footballer.


The HTTP request method is matched to the method name. (This rule applies only to GET, POST, PUT, and DELETE requests.)



/api/footballer will match the  GetPlayers() method


/api/footballer/1 will match the  GetFooballerById(1) method

We have a GET request, so the framework looks for a method on FootballerController controller. So there will be a call to the FootballerController controller and for a method whose name starts with "Get...". The FootballerController::GetPlayers() method will execute.

When we pass a parameter (id) to the controller the frameworks call the GetFooballerById, which takes the parameter and returns the footballer object.

The complete code for the Index.cshtml follows

<!DOCTYPE html>
<html lang="en">
<head>
    <title>ASP.NET Web API</title>
    <link href="../../Content/Site.css" rel="stylesheet" />
    <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript">
     
    </script>

    <script type="text/javascript">
        $(document).ready(function () {
      
            $.getJSON("api/footballer/",
            function (data) {
            
                $.each(data, function (key, val) {

             
                    var str = val.FirstName + " " + val.LastName;

                
                    $('<li/>', { text: str })
                    .appendTo($('#footballers'));
                });
            });
        });

        function find() {
            var id = $('#FootballerId').val();
            $.getJSON("api/footballer/" + id,
                function (data) {
                    var str = data.FirstName + " " + data.LastName;
                    $('#footballer').text(str);
                })
            .fail(
                function (jqXHR, textStatus, err) {
                    $('#footballer').text('Error: ' + err);
                });
        }
           
</script>
</head>
<body id="body" >
    <div class="main">
        <div>
            <h1>All Footballers</h1>
            <ul id="footballers"/>
        </div>
        <div>
            <label for="FootballerId">ID:</label>
            <input type="text" id="FootballerId" size="5"/>
            <input type="button" value="Search" onclick="find();" />
            <p id="footballer" />
        </div>

   

    </div>
</body>
</html>

In the second part (next blog post) I will be extending the application to insert,update and delete information.

Hope it helps!!!

Looking into Transaction Log size and clearing and database backups
In this post I would like to talk about the size of the transaction log and under what circumstances it clears in relation to recovery models and database backup types (Full, Differential, Log). I will also give a brief overview of recovery models, database Διαβάστε περισσότερα
Creating a complete ASP.Net MVC 4.0 application with Visual Studio 2012, C# , EF 5.0 (Code First) - part 6

I have decided to write a series of posts on how to write a small ASP.Net MVC 4.0 application.I will develop this application step by step and I will explain everything that you need to know in order to develop ASP.Net MVC 4.0 applications. This is the sixth post in this series. You can find the first one here , the second one here , third one here , the fourth one here and the fifth one here. Make sure you read and understand those posts.

In this post I will add some validations to our application through Code First Data Annotations and migrate those changes to our database through EF Code First Migrations.

Right now there is no validation for the fields Rating and Comment of the MovieReview entity. I want to have a validation rule applied to the Rating field that will accept only values 1 to 10 and it will be mandatory. The Comment field will only be 100 characters long and also mandatory.We also want to have the characters for the Name property of the Movie entity  restricted to 70 and the name of the Director restricted to 50 characters.

Both of these properties should be mandatory.

I am going briefly to introduce Data Annotations and how to use them in our Code First Entity framework applications. I have developed my data access layer with EF. We have 3 development paradigms in EF. We have Database First,Model First and Code First. The last one (Code First) is the one I have used for this application and frankly speaking it is gaining in popularity amongst developers.

I will use another post also found in this blog to demonstrate Data Annotations.In order to fully understand what I am talking about, you need to read this post titled Using the Code First approach when building ASP.Net applications with Entity Framework . It will take some time to create this application but it is necessary in order to follow along.

With Data Annotations we can configure our domain-entity classes so that they can take best advantage of the EF. We can decorate our entity classes with declarative attributes.Let me give you an insight on how EF Code First works.EF Code First at run time, looks at the entity-domain classes and infers from them the in-memory data that it needs to interpret the queries and interact with the database.For example it assumes that any property named ID represents the key property of the class.Data Annotations "live" inside the System.ComponentModel.DataAnnotations. We do add Data Annotations to our domain classes declaratively using attributes. You can also do that imperatively using the Fluent API.

 

1) Launch Visual Studio and launch the ASP.Net MVC 4.0 application we have been developing so far.

2) Have a look at my entity class Movie

    public class Μovie
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Director { get; set; }
        public DateTime YearReleased { get; set; }
        public virtual ICollection<MovieReview> Reviews { get; set; }
    }

If I go to the entity above and make one little change renaming the

         public string Name { get; set; }

         to

         [Required, MaxLength(70)]
        public string Name { get; set; }

my application will get an error if compile and view it in a browser. It will compile but when I click on the Movie link on the menu I get the results shown in the following picture

 

 

3)

Make sure you add a reference to the System.ComponentModel.DataAnnotations namespace in the class file

using System.ComponentModel.DataAnnotations;

Both entities after applying the data annotation attributes follow:

public class Μovie
    {
       
         public int Id { get; set; }
        [Required, MaxLength(70)]
        public string Name { get; set; }
        [Required, MaxLength(50)]
        public string Director { get; set; }
        public DateTime YearReleased { get; set; }
        public virtual ICollection<MovieReview> Reviews { get; set; }
    }

 

  public class MovieReview
    {
       
         public int Id { get; set; }
        [Required,Range(1,10)]
        public int Rating { get; set; }
        [Required, MaxLength(50)]
        public string Comment { get; set; }
        public int MovieId { get; set; }
    }
}

 

There are other data annotation attributes like Key,ConcurrencyCheck,[Table("MyTable",Schema="guest")] but it is impossible to cover everything in this post.

Now I am compiling again my application and then when I click on the Movie link on the menu I get the results shown in the following picture


 

So we receive an error. Well, there is an explanation for that behavior. The Entity Framework always checks the model that is in effect, that we just configured against the model it used originally to create the database.

4) The Entity Framework detected that there is something different in this model. When we apply the Required attribute to an property in the entity then this field in the database should be not null.

In order to solve that problem we must apply Code First Migrations

Code First Migrations is an Entity Framework feature introduced in version 4.3 back in February of 2012.

Before the addition of Code First Migrations (4.1,4.2 versions), Code First database initialisation meant that Code First would create the database if it does not exist (the default behaviour - CreateDatabaseIfNotExists).

The other pattern we could use is DropCreateDatabaseIfModelChanges which means that Entity Framework, will drop the database if it realises that model has changes since the last time it created the database.

The final pattern is DropCreateDatabaseAlways which means that Code First will recreate the database every time one runs the application.

That is of course fine for the development database but totally unacceptable and catastrophic when you have a production database. We cannot lose our data because of the way that Code First works.

Migrations solve this problem.With migrations we can modify the database without completely dropping it.We can modify the database schema to reflect the changes to the model without losing data.

5) EF Code First Migrations is not activated by default. We have to activate them manually and configure them according to our needs.

We will open the Package Manager Console from the Tools menu within Visual Studio.Then we will activate the EF Code First Migration Features by writing the command “Enable-Migrations”.  

Have a look at the picture below.

 

This adds a new folder Migrations in our project. A new auto-generated class Configuration.cs is created.Another class is also created[CURRENTDATE]_InitialCreate.cs and added to our project.

The Configuration.cs  is shown in the picture below.

 

6) Now we need to update the database.

In the Configurations.cs I change the AutomaticMigrationsEnabled value to true

    public Configuration()
        {
            AutomaticMigrationsEnabled = true;

        }

Then in the Package Manager Console, we write the following

Update-Database -Verbose

This will fail because EF understands that we take a column that was nvarchar(max) and make it nvarchar(50) e.t.c

Then in the Package Manager Console, we write the following

Update-Database -Verbose -Force

This statement will succeed.

That will force the changes to the database.

Have a look at the picture below

 

As you can see all the changes were made to the database.

Now if we run again our application and test it (try to violate the 1-10 values allowed in the rating field) I will get the error shown in the picture below

 

I know we covered a lot in this post but you must understand it, if you want to master EF Code First.

Hope it helps!!!

 

Creating a complete ASP.Net MVC 4.0 application with Visual Studio 2012, C# , EF 5.0 (Code First) - part 5

I have decided to write a series of posts on how to write a small ASP.Net MVC 4.0 application.I will develop this application step by step and I will explain everything that you need to know in order to develop ASP.Net MVC 4.0 applications. This is the fourth post in this series. You can find the first one here , the second one here the third one here and the fourth one here.  Make sure you read and understand those posts.

In this post I will add Search functionality to my application and 

 

1) Launch Visual Studio and open the application

2) We must add code to the _Layout.cshtml view in the Shared folder and more specifically to the menu. We must add an entry so someone can navigate to the Movie View.

The nav section becomes like this

                   <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                             <li>@Html.ActionLink("Movie", "Index", "Movie")</li>
                        </ul>
                    </nav>

3) Now we must delete the [Authorize] Action Filter attribute from the   public ActionResult Index() , that we previously entered. Now if we run the application we will see a new link in the menu, Movie.

Have a look at the picture below

 

5) Now we will add search functionality in our application.We need to add some code to the MovieController.cs file.We will add another public method (Search) that gets an input parameter(looks for name of the movie).The code is very easy to follow.I just use standard LINQ syntax. 

         public ActionResult Search(string searchString)
          {
            var movies = from movie in db.Movies
                              select movie;

            if (!String.IsNullOrEmpty(searchString))
            {
                movies = movies.Where(m => m.Name.Contains(searchString));
            }

            return View(movies);
           }

Now we need to implement the corresponding view.Right-click on the public ActionResult Search(string searchString) and select Add View.

 

Have a look at the picture below to see the settings you must add in the popup window (Add View)


 

 

Click Add.Have a look at the Search.cshtml file that was created inside theViews/Movie folder.Have a look at the generated code.You will see HTML helper objects and methods.Run your application and navigate to /Movie/Search. Append a query string such as ?searchString=godfather to the URL. The filtered entries(y) are displayed.

Have a look at the picture below

 

 

6) Now we need some sort of user interface,so that the user can enter the search string.I am going to make some changes to the Views\Movie\Search.cshtml view.

Open the file and under the 

<p>
    @Html.ActionLink("Create New", "Create")

add the following lines

         @using (Html.BeginForm()){   
         <p> Title: @Html.TextBox("SearchString") <br />  
         <input type="submit" value="Search" /></p>
        }


</p> 

We have the Html.BeginForm helper method that creates an opening <form> tag. The helper method causes the form to post to itself when the user submits the form by clicking the Search button. Have a look at the picture below

Have a look at the picture below

 

Up to this point, we have an application that one can add movies (name,director and the year released) edit and delete movies, search for movies by entering the name of the movie. Well me must move on and build the Reviews functionality, the ability for someone to write and edit a review for a particular movie.

7) When I click on the Details link on the http://localhost:59871/Movie , I get the following screen.

 

This is not very useful so I will delete the Details View in the Movie folder.

I will also comment out the Details method in the MovieController.cs

 

        // GET: /Movie/Details/5

        //public ActionResult Details(int id = 0)
        //{
        //    Μovie movie = db.Movies.Find(id);
        //    if (movie == null)
        //    {
        //        return HttpNotFound();
        //    }
        //    return View(movie);
        //}

I will also change the Index.cshtml in the Movie folder. I will replace the Details with the Reviews in the HTML.ActionLink

    <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Reviews", "Index", "Reviews", new { id=item.Id },null) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })

        </td>

8) Now we need to implement the ReviewsController controller so we can begin creating,editing,deleting reviews and associating them with movies.

Right-click the Controllers folder and create a new ReviewsController controller. Have a look at the picture below to set the appropriate settings

 

Click Add. Visual Studio will create the following

A ReviewsController.cs file in the project's Controllers folder.
A Reviews folder in the project's Views folder.
Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml, and Index.cshtml in the new Views\Reviews folder.


9)  Now we must change some of the code that was generated by the scaffolding.I will open the ReviewsController.cs and change the Index() method.

  public class ReviewsController : Controller
    {
        private MovieDBContext db = new MovieDBContext();

        //
        // GET: /Reviews/

  public ActionResult Index([Bind(Prefix="id")] int movieid)
        {
         

         var movie = db.Movies.Find(movieid);

            if (movie != null)
            {
           
                return View(movie);
            }
            return HttpNotFound();
        }

 

 As you can see this Action method must receive a parameter. This parameter represents a movie so we pass a movieid to this method. By using this [Bind(Prefix="id")] I just alias id with movieid.

10) Now we need to make some changes in the Index.cshtml in the Views/Reviews folder since we pass a movieid and not a reviewid

We must delete most of the code. The contents of the Index.cshtml should be

 @model MovieReviews.Models.Μovie

@{
    ViewBag.Title = "Index";
}

<h2>Reviews for @Model.Name</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>

 That should be all.Now I am going to create a partial view(_Reviews)

Have a look at the picture below


 

Click Add.

11) Now we must change the code in the partial view , _Reviews.

Have a look at the picture below to see the complete implementation

 

The code inside the <table> </table> tags, is the code I commented out in the Index.cshtml in the Reviews folder.

Now I must call this partial view from the Index.cshtml in the Reviews folder.

I add the code in bold

<h2>Reviews for @Model.Name</h2>

@Html.Partial("_Reviews",@Model.Reviews);
 


12) Now we need a way to associate the review to a movie when clicking on the link "Create New" for the review

<p>
    @Html.ActionLink("Create New", "Create",new { movieid=Model.Id})
</p>
 

Now we build and run the application again.When I click on the Movie link (http://localhost:59871/Movie) in the menu , I see the Reviews link for both my movies.I choose to click on the Reviews link for the first movie (The GodFather) and when I click on it, I see the following screen, where I can enter my review (after hitting Create New).

 

Finally I hit the Create button and my review for that movie has been entered.

Have a look at the picture below

 

 This is the code for the Create (HTTPGet) action inside the ReviewsController.cs     

     // GET: /Reviews/Create


        [HttpGet]
        public ActionResult Create(int movieid)
        {
          
            return View();
        }

We pass it the movieid for that movie as a parameter.

This is the code for the Create (HttpPost) action inside the ReviewsController.cs     

       //POST: /Reviews/Create

       [HttpPost]

       
        public ActionResult Create(MovieReview moviereview)
        {
            if (ModelState.IsValid)
            {
                db.Reviews.Add(moviereview);
                db.SaveChanges();
                  return RedirectToAction("Index", new { id = moviereview.MovieId});
            }

            return View(moviereview);
        }

This method will post back the form to the same url it came from.

13) Now let's see how to change slightly the code generated for the Edit method in the ReviewsController.cs 

  public ActionResult Edit(int id)
        {
            MovieReview moviereview = db.Reviews.Find(id);
            if (moviereview == null)
            {
                return HttpNotFound();
            }
            return View(moviereview);
        }

        //
        // POST: /Reviews/Edit/5

        [HttpPost]
        public ActionResult Edit(MovieReview moviereview)
        {
            if (ModelState.IsValid)
            {
                db.Entry(moviereview).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index", new { id = moviereview.MovieId });
            }
            return View(moviereview);
        }

 This method will post back the form to the same url it came from.

Now we build and run the application again.When I click on the Movie link (http://localhost:59871/Movie) in the menu , I see the Reviews link for both my movies.I choose to click on the Reviews link for the first movie (The GodFather) and when I click on it, I can see the reviews and hit the Edit link.

Have a look at the picture below

 

Finally I hit the Save button and my review for that movie has been edited.

14) Now let's see how to change slightly the code generated for the Delete method in the ReviewsController.cs 

// GET: /Reviews/Delete/5

        public ActionResult Delete(int id)
        {
            MovieReview moviereview = db.Reviews.Find(id);
            if (moviereview == null)
            {
                return HttpNotFound();
            }
            return View(moviereview);
        }

        //
        // POST: /Reviews/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            MovieReview moviereview = db.Reviews.Find(id);
            db.Reviews.Remove(moviereview);
            db.SaveChanges();
            return RedirectToAction("Index", new { id = moviereview.MovieId });
        }

This method will post back the form to the same url it came from.

Now we build and run the application again.When I click on the Movie link (http://localhost:59871/Movie) in the menu , I see the Reviews link for both my movies.I choose to click on the Reviews link for the first movie (The GodFather) and when I click on it, I can see the reviews and hit the Delete link.

Have a look at the picture below

 

Finally I hit the Delete button and my review for that movie has been deleted. 

Do not underestimate what we have accomplished so far. We have managed to develop an ASP.Net MVC 4.0 application where one can create,edit,delete,view and search for movies.

He can also create,edit,delete,view reviews for a particular movie.

In the next post I will talk about validation through data annotations and database migrations within the context of the Entity Framework Code First Paradigm.

Hope it helps!!!!