Saturday, April 6, 2013

Tutorial: Simple SignalR Hub with ASP.NET MVC 4

ASP.NET SignalR is a new HTTP technology that allows for a persistent connection between a client and a server. Check out http://signalr.net/ for more information on SignalR.

Here is a tutorial on creating a simple “Chat” SignalR server application using C# and ASP.NET MVC 4 in Visual Studio 2012. The client application will be an ASP.NET MVC View.

  1. Start Visual Studio 2012.
  2. File >> New Project… >> Visual C# >> Web >> ASP.NET MVC 4 Web Application. Name the application “MvcChatSignalR” then click on OK.
  3. Select the Empty template and the Razor view engine. For this example, there is no need to create a unit test project. Click on the OK button.
  4. In the NuGet “Package Manager Console”, type: Install-Package Microsoft.AspNet.SignalR. This will install all the bits necessary for SignalR.
  5. The “readme.txt” file pops up in Visual Studio. You are reminded that the “RouteTable.Routes.MapHubs();” code must be placed inside your Global.asax.cs file. Copy this code and paste it into the “Global.asax.cs” file right after “AreaRegistration.RegisterAllAreas();” as shown below:
    protected void Application_Start() {
    AreaRegistration.RegisterAllAreas();

    RouteTable.Routes.MapHubs();
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
    The SignalR route must be placed before the MVC route so that the requests for the hub are not swallowed up by the MVC route.



  6. Next, we will create a server-side hub. Create a folder named “Hubs” and in there create a class named “Chat.cs”. The Chat class inherits from the “Hub” base type and implements the server-side logic. Any public method declared in the hub class is callable from SignalR clients. Make sure the “Chat.cs” class file looks like this:
    public class Chat : Hub { 
    public void SendMessage(string nick, string message) {
    Clients.All.PublishMessage(nick, message);
    }
    }
    “PublishMessage” is not defined on the server-side application. This is a dynamic function that will be called in the client’s JavaScript. You can, if you like, annotate the server hub class with another name that the client can use. For example, we can give the server class the name “MessageSender” with annotation [HubName(“MessageSender ”)]. We are not doing this in our simple example.



  7. Since we created an empty MVC 4 project, we do not have a _Layout.cshtml page. Create a folder named “Shared” under Views. Inside the “Shared” folder, add a file named “_Layout.cshtml” with the following content:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title - My SignalR Chat Hub</title>
    <link href="~/favicon.ico" rel="shortcut icon"
    type="image/x-icon" />
    <link href="~/Content/Site.css" rel="stylesheet" />
    <meta name="viewport" content="width=device-width" />
    </head>
    <body>
    <div id="body">
    <section class="content-wrapper main-content clear-fix">
    @RenderBody()
    </section>
    </div>
    </body>
    </html>



  8. In the “Controllers” folder, add a new controller named “HomeController” using the “Empty MVC controller” template as shown below:
    image
  9. To create a view for the Index action method, right-click on “Index()” and select “Add View…”. This opens up the “Add View” dialog. y1giyb3b
  10. Simply click on the “Add” button without changing anything. This creates a plain file “Index.cshtml” in the in the Views/Home folder.
  11. Replace the code in “Index.cshtml” with the following code:
    <h2>Chat</h2>
    <label for="nick" >Your chat nickname:</label><br />
    <input type="text" name="nick" id="nick" />
    <br /><br />
    <label for="message" >Message:</label><br />
    <input type="text" name="message" id="message" maxlength="100" />
    <div id="chatWindow" style="width: 100%; height: 300px; overflow: scroll; border: 1px solid grey"></div>
    <br />
    <script src="~/Scripts/jquery-1.6.4.min.js"></script>
    <script src="~/Scripts/jquery.signalR-1.0.1.min.js"></script>
    <script type="text/javascript" src="/signalr/hubs"></script>
    <script>
    $(function () {
    // get handle to chat hub generated by SignalR
    var chatHub = $.connection.chat;

    // add method that can be called by the hub to update chat
    chatHub.client.publishMessage = function (nick, msg) {
    var chatWin = $("#chatWindow");
    chatWin.html(chatWin.html() + "<b>" + nick + "</b>: " + msg + "<br />");
    };

    // start the connection with the hub
    $.connection.hub.start();
    $(document).keypress(function (e) {
    if (e.which == 13) {
    // when the 'Enter' key is pressed, send the message to hub
    chatHub.server.sendMessage($("#nick").val(), $("#message").val());
    $("#message").val("");
    }
    });
    });
    </script>



  12. Make sure you adjust the names of the JavaScript files to suit your environment. Also, note that the JavaScript file “/signalr/hubs” is not a physical file on the server. It is dynamically generated by the server
  13. Compile and run the application. Open two different browsers (for example Chrome and IE) that point to the same URL. As you post a message from one browser, it shows up in both browsers. This is the power of SignalRdm2f3ch1

I hope you found this short tutorial useful. At this point, I am sure your mind is spinning with potential applications that you can build with this technology.

Saturday, March 16, 2013

Northwind-mania: CRUD operations against Web API Category table

Web API was introduced together with ASP.NET MVC 4. It is an ideal platform for building RESTful applications. In this tutorial, we will create a simple Web API server application using ASP.NET MVC 4. We will then consume the server application from a simple C# Command Line client application that executes CRUD operations against the Northwind Category table through Web API. The acronym CRUD stand for (C)reate (R)etrieve (U)date (D)elete.

Let us start by creating a Web API server web application using the famed Northwind database Category table.

Building the Web API server application

  • Start Visual Studio 2012
  • File >> New Project >> Visual C# >> Web >> ASP.NET MVC 4 Web Application
  • Name the Application NorthwindWebApi and click on OK
  • On the “Project Template” dialog, select the “Web API” template then click on OK
  • Right-click on the Models folder and choose: Add >> New Item >> ADO.NET Entity Data Model
  • Name the data model NorthwindModel.edmx
  • On the “Entity Data Model Wizard” dialog, select “Generate from database” then click Next
  • Click on “New Connection” and subsequently connect to the Northwind database that you have access to
  • When you are back at the “Entity Data Model Wizard” dialog, change the entity connection setting to NorthwindContext as this becomes the name of our Entity Framework context. Click on Next.
  • Select only the Categories table then click on Finish
  • Build once by hitting Ctrl-Shift-B on your keyboard so that the newly created classes are visible to your Visual Studio environment

Next we need to create a Web API controller for the Categories table. This is done very easily in ASP.NET MVC 4.0.

  • Right-click on the Controllers folder and choose: Add >> Controller
  • Make selections as shown in the dialog below:

image

  • When you are done, click on Add.
  • Have a look at the code in the CategoryController.cs class. You will notice that Visual Studio 2012 has conveniently produced for us all the action methods that cater for Post (Create); Get (Retrieve);  Put (Update); and Delete.

Now let us test to confirm that our Web API controller for categories actually works.

  • Hit Ctrl-F5 in Visual Studio to start your web application and view the home page in a browser.
  • Click on the API link on the top right-hand side. This takes you to the “ASP.NET Web API Help” page that shows you some documentation on how Web API works
  • Scroll down to the Category section. Click on “GET api/Category”. This shows you sample JSON and XML data that gets returned depending on the request header.
  • Click “Back” on the browser to return to the “ASP.NET Web API Help” page
  • In the address line, replace “Help” with api/Category. Your address URL should look similar to: http://localhost:14350/api/Category
  • If you are using IE, you will notice that a *.json file is being downloaded. If you open this .json file in Notepad you will notice that it contains all our categories serialized as JSON objects. We are now ready to build our C# command-line client.

Building the C# command-line Web-API client

  • In Visual Studio 2012 right-click on the solution and choose: Add >> New Project >> Visual C# >> Console Application
  • Name your console application WebApiClient
  • Let us first create a Category class on the client command-line application. This will be used to construct C# objects from de-serialized Category JSON objects. Create the following class:
public class Category {
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }

public override string ToString() {
string str = string.Format("ID={0}; Name={1}; Description={2}", CategoryId, CategoryName, Description);
return str;
}
}
We will need to use a NuGet package named “Microsoft ASP.NET Web API Client Libraries” for accessing Web API through HTTP.


  • Right-click on the command-line project “WebApiClient” and choose: Manage NuGet Packages. Enter “Microsoft ASP.NET Web API Client Libraries” in the search toolbox on the top right-hand side of the dialog. 

  • When the appropriate NuGet package appears, click on the Install button beside it.
image 




  • After the package installs, click Close to close the dialog

  • Add a reference to the “System.Net.Http” assembly

Client-side helper class


The CategoryWebApiHelper class will be used to simulate CRUD operations. In the command-line client application, create a class named CategoryWebApiHelper with the following instance variables and constructor:

public class CategoryWebApiHelper {
private string apiUrl = "";
HttpClient client = new HttpClient();
public CategoryWebApiHelper(string baseUrl, string apiUrl) {
this.apiUrl = apiUrl;
this.client.BaseAddress = new Uri(baseUrl);
// Add an Accept header for JSON format.
this.client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}


  • You will need to resolve the HttpClient and MediaMediaTypeWithQualityHeaderValue classes

The GET helper methods for data retrieval

We will need two get methods. One to retrieve all categories and one to retrieve a specific category by ID. First, add the following Get() method to the CategoryWebApiHelper class that essentially reads in all the categories from the database:
public List<Category> Get() {
HttpResponseMessage response = client.GetAsync(this.apiUrl).Result;
if (response.IsSuccessStatusCode) {
var categories = response.Content.ReadAsAsync<IEnumerable<Category>>().Result;
return categories.ToList();
}
else
return null;
}

Notice that async calls are being made to the server. The most interesting thing about the above code is that the ReadAsAsync method reads the response body and de-serializes it to a specified CLR type.


The HttpResponseMessage has a property IsSuccessStatusCode that indicates whether or not the response is OK.


Next, we will add a method that retrieves data for a Category object specified by the CategoryId.

public Category Get(int customerId) {
HttpResponseMessage response = client.GetAsync(this.apiUrl + customerId).Result;
if (response.IsSuccessStatusCode) {
var category = response.Content.ReadAsAsync<Category>().Result;
return category;
}
else
return null;
}




The POST helper method for data creation


Add the following method to create a Category record in the database:

public string PostInsert(Category category) {
HttpResponseMessage response = client.PostAsJsonAsync(apiUrl, category).Result;
if (response.IsSuccessStatusCode)
return string.Format("Category {0} inserted successfully", category.CategoryName);
else
return string.Format("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
Unlike with the get methods where we used client.GetAsync(), we use client.PostAsJsonAsync() in order to insert data. Notice that the PostAsJsonAsync() method takes two parameters – namely a relative URL and the Category object.

The PUT helper method for data updates


The helper method for updating category data is shown below:

public string PutUpdate(Category category) {
HttpResponseMessage response = client.PutAsJsonAsync(this.apiUrl + category.CategoryId, category).Result;
if (response.IsSuccessStatusCode)
return string.Format("Category {0} updated successfully", category.CategoryId);
else
return string.Format("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
The PutAsJsonAsync() method is used to update data. It takes two arguments. The first argument contains information about the CategoryId that is to be updated. The second argument is a Category object.

The DELETE helper method

Finally, the helper method for deleting data needs to know the primary key as shown below:
public string Delete(int categoryId) {
HttpResponseMessage response = client.DeleteAsync(this.apiUrl + categoryId).Result;
if (response.IsSuccessStatusCode)
return string.Format("Category {0} deleted successfully", categoryId);
else
return String.Format("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
The DeleteAsync() methods needs the CategoryId that is to be deleted.

Testing our Helper methods

In the Main() method of your Program.cs class, construct an instance of the CategoryWebApiHelper class as follows:
CategoryWebApiHelper helper = new CategoryWebApiHelper("http://localhost:14350/", "api/category/");
Adjust the above URL to suit your particular environment. Next, let’s just read all the items in the Categories table. Add the following code to the Main() method:
// get all Category items
List<Category> categories = helper.Get();
foreach (Category t in categories)
Console.WriteLine(t);
Console.WriteLine("============================================");


Run the command-line application by hitting Ctrl-F5 and you should see output similar to:
image 



Next, lets retrieve data for a specific category, say ID=5. Add this code to your main method:

// get one Category
Category category = helper.Get(5);
if (category != null)
Console.WriteLine(category);
Console.WriteLine("============================================");

This will result in output like the following:


image


Similarly, you can test our other helper methods for adding, updating, and deleting data.


Adding data

// Add a Category
var newCategory = new Category() {
CategoryName = "Teas",
Description = "Darjeeling"
};
Console.WriteLine(helper.PostInsert(newCategory));



Updating data

// Update Category with ID=12
Category category = helper.Get(12);
category.Description = "Peppermint";
Console.WriteLine(helper.PutUpdate(category));
Console.WriteLine(helper.Get(12));


Deleting data

// Delete Category with ID=12
helper.Delete(12);

It is strange how it is always easiest to delete.


I hope you found this post useful.

Thursday, November 29, 2012

Synchronizing SharePoint 2010 user profile with AD

There could be scenarios like these:

- an employee changed his or her name
- an employee changed their mobile phone number
- etc …

The profile information in SharePoint is outdated and needs to be refreshed from AD, where the information is more recent.

The powershell command to do this is:

Get-SPUser –Web http://site | Set-SPUser –SyncFromAD

This command cycles through all the SharePoint users and updates the profile. If you come across any errors it is because there are some accounts in SharePoint or on the local server environment that do not exist in SharePoint. If you go into the appropriate SharePoint site you will notice that profiles have been updated.

Thursday, October 18, 2012

SharePoint 2010 Web Part Error: A Web Part or Web Form Control on this page cannot be displayed or imported. You don’t have Add and Customize Pages permissions required to perform this action

 

I deployed  a SharePoint 2010 on a customer’s system. At first, everything worked OK when users with elevated privileges were testing the part. However, soon after read-only users started experiencing the above error. If a user’s privilege was escalated to “Designer”, it would start working again.

The solution to the problem is to find the SharePointProjectItem.spdata file associated with the web-part and change the IsSafeAgainstScript to true in the <SafeControl..> element.

For Example:

<SafeControls>
    <SafeControl Name="SafeControlEntry1"
        Assembly="$SharePoint.Project.AssemblyFullName$"
        Namespace="Medhat.Ca.MyWebpart"
        TypeName="*"
        IsSafe="true"
        IsSafeAgainstScript="true" />
</SafeControls>

The explanation for this error is that users with privileges below "Design” are not allowed to add web-parts into web pages.

Saturday, September 8, 2012

Dual boot Windows 8 from a VHD file under Windows 7

Windows 8 has been available on MSDN for almost a month now. In addition, Windows 8 is now available to students under the Dreamspark program. At the moment, there are many among us who are using Windows 7 as our main operating system on our laptops and desktops. Some of us are willing to explore Windows 8 without necessarily losing our Windows 7 environment. A good way to accomplish this is to install Windows 8 as a VHD instance.

image

The assumption here is that you are installing Windows 8 on a computer that already has Windows 7.

Here are some advantages to using a VHD file to dual boot from:

  1. You can easily backup the VHD drive, thus backing up your entire Windows 8 operating system. It is particularly useful to do a backup of the VHD file right before installing a major piece of software that could potentially mess up your environment.
  2. You can move your VHD file from one computer to another.
  3. It acts exactly as if the Windows 8 operating is installed directly on a separate partition on your hard drive.
  4. You need not go through the pain of creating any additional partition on your hard drive.

Below are the steps you need to follow in order to accomplish this.

Steps for Installing Windows 8 in a VHD drive

  • Create a DVD (or bootable USB) from the ISO image that you obtained with Windows 8 on it.
    • To create a bootable USB from your ISO image, download a free utility from Microsoft at http://tinyurl.com/4qfdm4x.  Here’s what the download looks like:

image

    • To create a bootable DVD from your ISO image, place a blank DVD in the drive and simply double click on the ISO file. Windows 7 has a built-in application named “Windows Disk Image Burner”.

image

Alternatively, you can use any other application that is capable of burning a DVD from an ISO file. I recommend a freely available application named “imgburn” that I use and like.
  • Reboot your computer from the DVD (or USB). This may require you to get into the BIOS settings of your computer in order to rearrange the boot sequence of your various storage devices.

image

  • At the “Install Windows 8” screen, hit the Shift-F10 keys to open a command prompt.
  • When at the command prompt, type "diskpart <enter>". Wait until you see the command prompt “DISKPART >”.
  • In order to see a list of all available volumes, type "list volume <enter>". Identify the drive name that has ample available disk space which you want to install the VHD into. The drive letter will be under the column entitled “Ltr”.
  • In this example, we will create the VHD file on drive D:. Make sure to replace D: with the appropriate drive letter that fits your situation. You can create either a fixed or dynamic VHD file:
    • Creating a fixed VHD file: A fixed VHD file will allocate the entire maximum size that you set, regardless of whether or not the operating system uses that much space. Note that once you set a size, you cannot increase it in future, so make sure you are reasonably generous in choosing a maximum size. The following command assumes that you will be allocating a fixed VHD drive of 40GB (1GB = 1024 MB):
    • create vdisk file=D:\win8.vhd maximum=40960

      Note: In the command above, substitute D: with the drive letter that suits your situation. You can use any other name you like instead of win8.
    • Creating a dynamic expandable VHD file: A dynamic VHD file will initially be as large as the data used by the VHD. This can grow to the maximum size set when you create the VHD file. In the example below I will create a dynamic VHD drive that can grow to a maximum size of 40GB:
    • create vdisk file=D:\win8.vhd maximum=40960 type=expandable

  • Wait until the VHD drive has been 100% created. Next we need to select the VHD that was created. This is done by entering a command similar to the one below, depending on the drive letter and VHD file name you used:
  • select vdisk file=D:\win8.vhd
  • The next step is to attach to the VHD file. This is done with the the command:
  • attach vdisk
  • At this point we have done all that is necessary to create a VHD file and attach to it. We can now exit the DISKPART prompt. To do so, enter the following command:
  • exit

  • Close the command prompt window by clicking on the X located on the top-right-hand side of the window. We can now continue with the regular Windows 8 install.
  • Click “Next” on the “Windows Setup” dialog.

image

  • Click on the “Install Now” button on the next dialog.
  • The next dialog will ask you for your product key. Enter your product key and click “Next”.
  • Accept the license terms on the next dialog by clicking on the “I accept the license terms” checkbox then click on the “Next” button.
  • The next dialog will enable you to choose whether you want to do an upgrade or custom install. Since we want to install Windows 8 from scratch, we will choose the second option “Custom: Install Windows only (advanced)” by clicking on it.
  • The next window is very critical because it is at this point that you select the drive that will hold the new operating system. The primary manner by which you can identify this drive is by the size of the drive (I.E. in the case of this example it is 40GB) and the fact that it is still “Unallocated Space”.
    • Note that you run the risk of losing data if you choose the wrong drive.
    • Ignore the message “Windows can’t be installed on this drive. (Show details)

    Select the correct drive then click “Next”.

  • The rest is should proceed smoothly. When the installation is finished, Windows 8 will be set as the default operating system. You will, however, be given the option to boot into Windows 7 if you so desire.

Steps for removing the Windows 8 VHD

  • Boot into Windows 7
  • Find the Windows 8 VHD file on your hard drive
  • Delete the Windows 8 VHD file
  • Reboot the computer

Hope this is useful to you.

References:

Tutorial: Windows 8 VHD - Create at Boot to Dual Boot with

Monday, August 27, 2012

Uploading documents into SharePoint 2010 using OData

I experienced some pain when asked to develop a utility to upload documents into SharePoint 2010 using OData. Therefore, I naturally decided on this post in order to save others the pain I went through. This post explains how to do it using a simple client-side C# command-line application:

Step 1:

Create a C# command-line application in Visual Studio 2010 on the same box as your SharePoint 2010 server. Add a proxy to the SharePoint 2010 OData service on your server. This is done by right-clicking on your project “References” node and choosing “Add Service Reference …”.

image

The service that needs to be consumed is listdata.svc. Enter a URL similar to http://myserver/_vti_bin/listdata.svc then click on the “Go” button. Once the service is found, give the service NameSpace the name ListdataServiceReference.

Step 2:

I placed a text file named bogus.txt in the root of my c: drive with some arbitrary content. I also created a document library named BogusDocumentLibrary in the root site of my SharePoint server. Here is the upload() method code for uploading file c:\bogus.txt into the document library named BogusDocumentLibrary.

private static void upload() {
    string sharePointSvc = "
http://myserver/_vti_bin/listdata.svc";

    using (FileStream file = File.Open(@"c:\bogus.txt", FileMode.Open)) {
        ListdataServiceReference.HomeDataContext ctx
            = new ListdataServiceReference.HomeDataContext(new Uri(sharePointSvc));

       // ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;

        string username = "alice";
        string password = "wonderland";
        string domain = "myserver";

        ctx.Credentials = new System.Net.NetworkCredential(username, password, domain);

        string path = "/BogusDocumentLibrary/Bogus.txt";
        string contentType = "plain/text";
        ListdataServiceReference.BogusDocumentLibraryItem documentItem = new ListdataServiceReference.BogusDocumentLibraryItem()
        {
            ContentType = contentType,
            Name = "Bogus",
            Path = path,
            Title = "Bogus"
        };

        ctx.AddToBogusDocumentLibrary(documentItem);

        ctx.SetSaveStream(documentItem, file, false, contentType, path);

        ctx.SaveChanges();
    }
}

Needless to say, you must resolve the missing System.IO namespace.

Context
The name of the proxy class representing your context is named depending on your site’s name. In my case, my site is named home so the proxy context class is HomeDataContext.

Credentials
If you are accessing the service on the same box or domain as the server then it suffices that you pass on the default credentials with “System.Net.CredentialCache.DefaultCredentials”. Otherwise, if you are on a different domain then you should use the technique described in the code above where the username, password, and domain with access rights to the SharePoint site are passed on to the server.

Document Properties
The item proxy class name that represents the document library depends on the name given to it. In my case, I named the document library BogusDocumentLibrary so the item proxy class name is BogusDocumentLibraryItem. Once an instance of this class in instantiated then the various properties such as ContentType, Name, Path, and Title must be set.

Upload document
Finally, these three lines are responsible for uploading the document:

ctx.AddToBogusDocumentLibrary(documentItem);
ctx.SetSaveStream(documentItem, file, false, contentType, path);
ctx.SaveChanges();

Finally, you can call the upload() method from within your main method and it should all work as long as the appropriate server, text file, and document library exist.

Thursday, July 26, 2012

Northwind-mania: Upgrading Northwind.mdf database file from SQL Server 2005/2008 to LocalDB\v11.0

Visual Studio 2012 comes with a new small light-weight database named LocalDB\v11.0. You can find out the default database used by Visual Studio 2012 by checking out TOOLS >> Options… >> Database Tools >> Data Connections:

image

If you have a SQL2005 or SQL2008 database and wish to use it in a Visual Studio 2012 application, you should upgrade it to LocalDB\v11.0 format. Here’s what I did when I came across this predicament. I used the usual Northwind.mdf SQL2008 database for this post.

- In Visual Studio 2012  “Server Explorer”, right-click on “Data Connections” and select “Add Connections…”

image

- Click the “Change…” button on the “Add Connection” dialog:

image

- Choose “Microsoft SQL Server Database File” then click OK. You will be returned to the “Add Connection” dialog.

image

- Navigate to the location of your Northwind.mdf file by clicking the “Browse…” button, then click OK.

image

- Visual Studio 2012 will detect that the database is not of LocalDB\v11.0 format and will display this message:

image

- Click “Yes” so that your SQL200x database gets upgraded to LocalDB\v11.0. Upon completion of the upgrade process you will be able to view all your database objects in Server Explorer:

image

Hope this helps.