Windows web service authentication in IIS Express

When you develop a SOAP web service in Visual Studio 2013 the IDE uses IIS Express for testing. To set up Windows authentication in IIS Express follow the steps below:

Create a Local Security Group on your computer

  • Right click Computer and select Manage
  • On the left side expand Local Users and Groups
  • Right click the Groups folder and select New Group
  • Create a group with the name WebserviceUsers for the users of the web service
  • Right click the Users folder and select New User
  • Create a user and add it to the WebserviceUsers security group

Add the following lines to the  <system.web> section of the Web.config file of your web service application

<authentication mode=”Windows”/>
<authorization>
<allow roles=”WebserviceUsers”/>
<deny users=”*”/>
</authorization>

Set up IIS Express for Windows authentication

  • Select the web service project in the Solution Explorer
  • In the View menu select Properties Window
  • Disable Anonymous Authentication and enable Windows Authentication
    Visual Studio IIS Express Windows Authentication Properties Window

 

In the caller application call the web service with user name and password

  • Add the following lines to your class to supply the credentials
private Webservice.Service _Webservice = new Service();

// Constructor
public Business() {
    string webserviceUrl = "Webservice_Url";
    string webserviceUserName = "Webservice_UserName";
    string webservicePassword = "Webservice_Password";
    _Webservice.Url = webserviceUrl;
    ICredentials credentials = new NetworkCredential(webserviceUserName, webservicePassword);
    _Webservice.Credentials = credentials;
}

How to add tooltip to a Windows Form

In Windows Form applications the tooltip functionality is not built into the controls as in HTML objects.

To add tooltip to your controls on Windows Forms

  • Open the Windows Form in the designer
  • Drag the ToolTip control from the Common Controls section of the Toolbox to the form. The ToolTip control will be placed at the bottom margin of the design surface outside of the visible area of the form.
  • A new item appears in the Misc section of the property list of the form controls (buttons, textboxes, etc): ToolTip on toolTip1
  • Enter the text there you want the users to see when they hover above the control.

How to add a DataGridView to a Windows Form

To display data in a DataGridView on a Windows Form

  • Add a new form to the Win Form Application project
  • Drag a BindingSource from the Toolbox to the form
    Visual Studio Toolbox Data

 

  • The bindingSource object appears below the form
    Visual Studio DataGridview Binding DatSource insert

 

  • Rename the Binding Source
    • Select the bindingSource1 object below the form
    • Press F4 to display the Properties
    • Change the Name property to reflect the purpose of the object
      Visual Studio DataGridview Binding DatSource properties

 

  • Select the DataSource item in the Data section and click the Add Project Data Source… link
    Visual Studio DataGridview Binding DatSource properties select data source

The name is misleading. At this step we are not selecting the source of the data, we are selecting the object that describes the data row. The DataGridView will generate the columns based on the object we will select here.

  • To load the data from a class select Object as the Data Source Type and click Next
    Visual Studio DataGridview Binding Data Source properties choose data source type

 

  • Select the object that describes the data row you want to display
    Visual Studio DataGridview Binding Data Source properties select data object

 

  • Drag a DataGridView from the Toolbox to the form
    Visual Studio Toolbox Data data grid view

 

  • Select the small arrow at the upper right corner of the DataGridView to open the Tasks dialog
  • Click the down arrow next tot the Choose Data Source list
  • Select the Binding Data Source that you added to the form
    Visual Studio DataGridview select binding data source

 

  • Click the Edit Columns link to set the visibility of the columns
    Visual Studio DataGridview Edit Columns

 

  • To hide a column set the Visible attribute in the Appearance section to False
    Visual Studio DataGridview Column visibility
  • To load data into the DatGridView add the following code to the constructor of the form. In this example the GetUsers() method returns an array of UserView objects
    // Load the data into the DataGridView
    bindingSourceUsers.DataSource = _business.GetUsers();
  • To hide the row selector column on the left side of the data add the following to the constructor of the form. This option is not included in the property sheet of the DataGridView, so we have to set it in the code.
    dataGridView1.RowHeadersVisible = false;

How to test SOAP web services from outside of the server with a web browser

SOAP web services that accept primitive type arguments (string, int, etc.) can be tested from a web browser.
For security reasons this feature is disabled if the web browser runs on another machine. To enable testing the SOAP web services in the test environment from another machine add the following to the system.web section of the Web.config file:

<webServices>
    <protocols>
        <add name="HttpPost"/>
        <add name="HttpGet"/>
    </protocols>
</webServices>

DbArithmeticExpression arguments must have a numeric common type

The Microsoft Visual Studio 2013 Entity Framework database query does not support the subtraction of two dates to calculate TimeSpan.

For example the following statement will throw a runtime error:

site.VisitFrequencySec < ((TimeSpan)(dtNow - site.LastVisitDate)).TotalSeconds)

To solve the problem create a computed database column to calculate the difference between the dates and use the computed value for comparison.

Column definition:

[SecondsSinceLastVisit]  AS (datediff(second,[LastVisitDate],getdate()))

Now you can use the computed column in the C# Entity Network comparison.

site.VisitFrequencySec < site.SecondsSinceLastVisit

The underlying provider failed on Open

When you get the following error message in Microsoft Visual Studio 2013 check the inner exception.

System.Data.Entity.Core.EntityException was unhandled
  HResult=-2146233087
  Message=The underlying provider failed on Open.
  Source=EntityFramework

The inner exception gives you detailed information on the real cause of the error. Most of the time the inner exception is the following:

InnerException: System.Data.SqlClient.SqlException
       HResult=-2146232060
       Message=Cannot open database “…” requested by the login. The login failed.
Login failed for user ‘…’.
       Source=.Net SqlClient Data Provider
       ErrorCode=-2146232060

Check the rights of the user. Most likely the specified user does not have access to the database.

 

The Entity Framework provider … could not be loaded

When you create a new Microsoft Visual Studio 2013 project that uses the Entity Framework you may get the following error message:
The Entity Framework provider type ‘System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer’ registered in the application config file for the ADO.NET provider with invariant name ‘System.Data.SqlClient’ could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

  • Add the EntityFramework NuGet package to the Data Access project that accesses the database and the Web Application or Web Service project that calls the project
    • Right click the project in Solution Explorer
    • Select Manage NuGet Packages
    • On the left side select Online
    • On the right side enter EntityFramework into the search field
    • Click Install next to the EntityFramework package
  • Make sure your app config file contains the following lines:

 

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="v11.0" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  </providers>
</entityFramework>
  • Your project should contain a reference to EntityFramework.SqlServer.dll
  • Add the following line to the constructor of the class that accesses the database
var type = typeof(System.Data.Entity.SqlServer.SqlProviderServices);
  • Add the System.Data.Entity reference to the project accessing the database

How to migrate the Visual Studio 2013 user database to SQL Server 2008

When you create a new web application in Microsoft Visual Studio 2013 the user database it creates is version 706. SQL Server 2008 can only open databases up to version 663 or earlier. To migrate the new Visual Studio 2013 databases to SQL Server 2008 script the database tables and create them again in the SQL Server 2008 Management Studio.

  • Start Visual Studio 2013
  • Create a new web application with user authentication
  • On the left side select the Server Explorer
  • Click the arrow next to the Data Connections
  • Click the arrow next to DefaultConnection
  • Click the arrow next to Tables
  • Right click each table and select Open Table Definition

visual studio script database table

At the bottom of the screen the table definition script appears

visual studio script database table result

You have to create the tables in the appropriate order, to satisfy the foreign key references. The script below creates the tables in the right order:

CREATE DATABASE your_database
GO
USE your_database
GO

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[__MigrationHistory] (
    [MigrationId]    NVARCHAR (150)  NOT NULL,
    [ContextKey]     NVARCHAR (300)  NOT NULL,
    [Model]          VARBINARY (MAX) NOT NULL,
    [ProductVersion] NVARCHAR (32)   NOT NULL,
    CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY CLUSTERED ([MigrationId] ASC, [ContextKey] ASC)
);
GO            

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[AspNetRoles] (
    [Id]   NVARCHAR (128) NOT NULL,
    [Name] NVARCHAR (MAX) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[AspNetUsers] (
    [Id]            NVARCHAR (128) NOT NULL,
    [UserName]      NVARCHAR (MAX) NULL,
    [PasswordHash]  NVARCHAR (MAX) NULL,
    [SecurityStamp] NVARCHAR (MAX) NULL,
    [Discriminator] NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[AspNetUserClaims] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [ClaimType]  NVARCHAR (MAX) NULL,
    [ClaimValue] NVARCHAR (MAX) NULL,
    [User_Id]    NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserClaims] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_User_Id] FOREIGN KEY ([User_Id]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[AspNetUserLogins] (
    [UserId]        NVARCHAR (128) NOT NULL,
    [LoginProvider] NVARCHAR (128) NOT NULL,
    [ProviderKey]   NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserLogins] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [ProviderKey] ASC),
    CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[AspNetUserLogins]([UserId] ASC);
GO

--  ---------------------------------------------------------------------

CREATE TABLE [dbo].[AspNetUserRoles] (
    [UserId] NVARCHAR (128) NOT NULL,
    [RoleId] NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
    CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_RoleId]
    ON [dbo].[AspNetUserRoles]([RoleId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[AspNetUserRoles]([UserId] ASC);
GO

Execute the script in the SQL Server Management Studio

Microsoft Azure – Storage – Part 5 – Delete blobs with a .NET application

In the prior article of the Microsoft Azure storage series we have downloaded a file (blob) from the container. In this part we will add a method to delete a blob in the Azure storage container.

Delete a blob  in the storage container

Add the DeleteBlob method to the Azure_Helper

  • Open the Azure_Helper.cs file in the Azure_Helper project
  • Add the following method to the class
/// <summary>
/// Deletes a blob in the Azure storage
/// </summary>
/// <param name="sContainerPath"></param>
/// <param name="sBlobName"></param>
public void DeleteBlob(string sContainerPath, string sBlobName) {

    // Create the blob client.
    CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

    // Retrieve reference to a previously created container.
    CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

    // Retrieve reference to a blob named "myblob.txt".
    CloudBlockBlob blockBlob = container.GetBlockBlobReference(sBlobName);

    // Delete the blob.
    blockBlob.Delete();
}

Call the Azure_Helper from the Console Application

  • Open the Program.cs file in the Azure_ConsoleApplication
  • Add the following to the end of the Main method
// Delete the blob from the Azure storage
azureHelper.DeleteBlob(sContainerPath, sBlobName);

When you are testing the application the first time you can place a break point to the line that calls the DeleteBlob method and use the Azure manager  at https://manage.windowsazure.com  to follow the creation and deletion of the blob in the Azure storage container.

Microsoft Azure – Storage – Part 3 – List the contents of the container with a .NET application

In the second part of the Azure Storage series we have developed a .Net application that can create a Microsoft Azure storage  container and upload files into it. Today we will extend the functionality of our application to list the files in the container.

List the files in the container

First let’s create a class that represents the Azure Blob. This way we can isolate our console application from the Azure Storage system, so in the future it can work with any cloud storage systems.

Add a file to the Azure_Helper project to store enumerations

  • Right click the Azure_Helper project and select Add -> Class
  • Name the class Enums
  • Add an enumeration outside of the class definition. The file should look like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace nsAzure_Helper {

    public class Enums {
    }

    public enum ItemType {
        undefined
        , BlobDirectory
        , BlockBlob
        , PageBlob

    }
}

Add a class to the Azure_Helper to represent a file or directory in the cloud

  • Right click the Azure_Helper project and select Add -> Class
  • Name the class CloudItem
  • To make the class public enter the word public in front of the word class
public class CloudItem
  • Add public properties to the class. The class definition should look like this:
public class CloudItem {

    public long Length { get; set; }
    public Uri Uri { get; set; }
    public ItemType Itemtype { get; set; }

}
  • Open the Azure_Helper.cs file in the Azure_Helper project
  • Add a new method to list the content of the container
/// <summary>
/// Returns the list of cloud items in the container
/// </summary>
/// <param name="sContainerPath"></param>
/// <returns></returns>
public List<CloudItem> GetContainerItems(string sContainerPath) {

    List<CloudItem> itemList = null;

    // Create the blob client. 
    CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

    // Retrieve reference to a previously created container.
    CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

    if (null == container) {
        // No container found
        return itemList;
    }

    // Create an instance of the item list
    itemList = new List<CloudItem>();

    // Loop over items within the container and output the length and URI.
    foreach (IListBlobItem item in container.ListBlobs(null, false)) {

        // Create a new instance of the Cloud Item
        CloudItem cloudItem = new CloudItem();

        if (item.GetType() == typeof(CloudBlockBlob)) {
            // This is a Block Blob

            CloudBlockBlob blob = (CloudBlockBlob)item;

            cloudItem.Itemtype = ItemType.BlockBlob;
            cloudItem.Length = blob.Properties.Length;
            cloudItem.Uri = blob.Uri;

        } else if (item.GetType() == typeof(CloudPageBlob)) {
            // This is a Page Blob

            CloudPageBlob pageBlob = (CloudPageBlob)item;

            cloudItem.Itemtype = ItemType.PageBlob;
            cloudItem.Length = pageBlob.Properties.Length;
            cloudItem.Uri = pageBlob.Uri;

        } else if (item.GetType() == typeof(CloudBlobDirectory)) {
            // This is a Directory

            CloudBlobDirectory directory = (CloudBlobDirectory)item;

            cloudItem.Itemtype = ItemType.BlobDirectory;
            cloudItem.Uri = directory.Uri;

        }

        // Add the item to the list
        itemList.Add(cloudItem);

    }

    return itemList;

}

The method above returns a list of Cloud Items.

Let’s call the method from our Console Application

  • Open the Program.cs file in the Azure_ConsoleApplication project
  • Add the following code to the existing lines
// Get the list of items in the Container
List<CloudItem> itemList = azureHelper.GetContainerItems(sContainerPath);
if (null != itemList){

    foreach (CloudItem item in itemList){

        if (ItemType.BlockBlob == item.Itemtype) {

            Console.WriteLine("Block blob of length {0}: {1}", item.Length, item.Uri);

        } else if (ItemType.PageBlob == item.Itemtype) {

            Console.WriteLine("Page blob of length {0}: {1}", item.Length, item.Uri);

        } else if (ItemType.BlobDirectory == item.Itemtype) {

            Console.WriteLine("Directory: {0}", item.Uri);
        }

    }
}

Console.WriteLine("Press a key to exit");
Console.Read();

The Program.cs file should look like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using nsAzure_Helper;

namespace Azure_ConsoleApplication {
	class Program {
		static void Main(string[] args) {

			// Create an instance of the Azure Helper
			Azure_Helper azureHelper = new Azure_Helper();

			string sContainerPath = "test1";
			bool bMakeContainerPublic = true;
			string sBlobName = "blob1";
			string sSourceFilePath =  @"D:\MediaFiles\Audio\Music.wav";

			// Create a public container
			azureHelper.CreateContainer(sContainerPath, bMakeContainerPublic);

			// Upload an audio file
			azureHelper.UploadFile(sContainerPath, sBlobName, sSourceFilePath);

			// Get the list of items in the Container
			List itemList = azureHelper.GetContainerItems(sContainerPath);
			if (null != itemList){

				foreach (CloudItem item in itemList){

					if (ItemType.BlockBlob == item.Itemtype) {

						Console.WriteLine("Block blob of length {0}: {1}", item.Length, item.Uri);

					} else if (ItemType.PageBlob == item.Itemtype) {

						Console.WriteLine("Page blob of length {0}: {1}", item.Length, item.Uri);

					} else if (ItemType.BlobDirectory == item.Itemtype) {

						Console.WriteLine("Directory: {0}", item.Uri);
					}

				}
			}

			Console.WriteLine("Press a key to exit");
			Console.Read();

		}

	}
}

In the next article we will learn how to download files from the Microsoft Azure storage.