Welcome to EMC Consulting Blogs Sign in | Join | Help

Shailen Sukul's Blog

  • ASP.Net MVC4 Mobile Tutorial - Part 3

    Summary

    Continuing from our discussion around a sample ASP.Net MVC4 Mobile application, this final post will discuss the final piece; the UI and how it all comes together.


    You can download the full sample from here.

    The User Interface

    The default project uses the jQuery mobile plugin to target mobile devices. The jQuery mobile plugin is touch-optimized for smartphones and tablets and it targets iOS, Android, Blackberry, Bada, Windows Phone, Palm WebOS, Symbian and MeeGo.

    Lets start with the JavaScript logic, which will perform the interaction between the HTML UI and the JSON web service.

    • In the Scripts folder, add a folder called com then sukul underneath that and finally babyfeeding underneath that
    • In the final babyfeeding folder, add a JavaScript file and called it proxy.js
    • Copy and paste the following code into the js file
    • if (Sukul == undefined) var Sukul;
      if (!Sukul) Sukul = {};
      
      //Constructor
      Sukul.Proxy = function (siteBaseUrl) {
          // constructor
          Sukul.Proxy.prototype.baseUrl = siteBaseUrl;
          Sukul.Proxy.prototype.heartBeatUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/HeartBeat";
          Sukul.Proxy.prototype.FeeedingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddFeedingEntry"
          Sukul.Proxy.prototype.DiaperingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddDiaperingEntry"
      }
      
      Sukul.Proxy.prototype = {
          CallWebService: function (url, input, successCallBack, errorCallBack) {
              //Uncomment the next line to support JSONP
              //url = url + "?callback=?";       
              $.ajax({
                  async: false,
                  cache: false,
                  type: "GET",
                  contentType: "application/json; charset=utf-8",
                  url: url,
                  dataType: "json",
                  data: input,
                  success: successCallBack,
                  error: errorCallBack
              });
      
          },
      
          HeartBeat: function (successFunction, failFunction) {
              this.CallWebService(this.heartBeatUrl, "", successFunction, failFunction);
          },
          AddFeeding: function (UserId, FeedType, FeedAmount, successFunction, failFunction) {
              var input = "UserId=" + UserId + "&FeedType=" + FeedType + "&FeedAmount=" + FeedAmount;
              this.CallWebService(this.FeeedingUrl, input, successFunction, failFunction);
          },
          AddDiapering: function (UserId, DiaperType, successFunction, failFunction) {
              var input = "UserId=" + UserId + "&DiaperType=" + DiaperType;
              this.CallWebService(this.DiaperingUrl, input, successFunction, failFunction);
          }
      };
    • The JavaScript is structured using objects and namespaces. Every JavaScript object contains an inner class called Prototype. By defining methods on this inner class, we can encapsulate object variables and methods and share them across concrete instances of the class. In the code above, the Proxy object defines the following methods:
      • CallWebService - helper method for invoking the JSON service
      • HearBeat - invokes the Heat method call for diagnostics
      • AddFeeding - creates a feed entry by taking input from the form and invoking the web service
      • AddDiapering - creates an entry for a diaper change by taking input from the form and invoking the web service
    • Finally, we encapsulate the Proxy object inside the Sukul object to create a namespace so that the proxy object can be referenced like so: Sukul.Proxy

    The Index.cshtml View

    Copy and paste the following code for the Index page

    @{
        ViewBag.Title = "Baby Log Home";
    }
    
    <script type="text/javascript">
        $(document).ready(function () {
            $("#btnSubmit").click(function () {
    
                $("#txtLastEntry").val("Last: ");
    
                // Create the proxt class
                var proxy = new Sukul.Proxy("@Request.Url.GetLeftPart(UriPartial.Authority)");
                // Add the feeding entry
                if ($("#chkFeed").attr("checked") != undefined && $("#chkFeed").attr("checked") == "checked") {
                    proxy.AddFeeding("@Membership.GetUser().UserName", $("#drpType").val(), $("#drpAmount").val(),
                        function (result) {
                            // succeeded
                            $("#txtLastEntry").val($("#txtLastEntry").val() + $("#drpAmount option:selected").text() +
                            " of " + $("#drpType option:selected").text());
                        },
                        function (jqXHR, textStatus, errorThrown) {
                            // failed
                            var err = "Details: " + textStatus;
                            if (errorThrown != undefined) {
                                err += "\rMore details : " + errorThrown;
                            }
                            alert(err);
                        });
                }
                // Add the diapering entry
                if ($("#chkDiaper").attr("checked") != undefined && $("#chkDiaper").attr("checked") == "checked") {
                    proxy.AddDiapering("@Membership.GetUser().UserName", $("#drpDiaper").val(),
                        function (result) {
                            // succeeded
                            $("#txtLastEntry").val($("#txtLastEntry").val() + ", " + 
                            $("#drpDiaper option:selected").text() + " diaper");
                        },
                        function (jqXHR, textStatus, errorThrown) {
                            // failed
                            var err = "Details: " + textStatus;
                            if (errorThrown != undefined) {
                                err += "\rMore details : " + errorThrown;
                            }
                            alert(err);
                        });
                }
            });
        });
    </script>
    <div data-role="fieldcontain" data-inset="true">
        <fieldset data-role="controlgroup">
            <legend>Feed Details</legend>
            <input id='chkFeed' name='chkFeed-1' type="checkbox" checked="checked" class="custom" />
            <label for="chkFeed">
                Log Feed</label>
        </fieldset>
        <fieldset data-role="controlgroup">
            <legend>Feed Type:</legend>
            @Html.DropDownList("drpType", new List<SelectListItem> { 
                new SelectListItem { Text="Bottle", Value="Bottle", Selected=true }, 
                new SelectListItem { Text="Left", Value="Left" }, 
                new SelectListItem { Text="Right", Value="Right" }, 
            })
        </fieldset>
        <fieldset data-role="controlgroup">
            <legend>Amount:</legend>
            @Html.DropDownList("drpAmount", new List<SelectListItem> { 
                new SelectListItem { Text="0.5 oz.", Value="0_5" }, 
                new SelectListItem { Text="1.0 oz.", Value="1_0" }, 
                new SelectListItem { Text="1.5 oz.", Value="1_5" }, 
                new SelectListItem { Text="2.0 oz.", Value="2_0" }, 
                new SelectListItem { Text="2.5 oz.", Value="2_5", Selected=true }, 
                new SelectListItem { Text="3.0 oz.", Value="3_0" }, 
                new SelectListItem { Text="3.5 oz.", Value="3_5" }, 
                new SelectListItem { Text="4.0 oz.", Value="4_0" }, 
                new SelectListItem { Text="4.5 oz.", Value="4_5" }, 
                new SelectListItem { Text="5.0 oz.", Value="5_0" }, 
                new SelectListItem { Text="5.5 oz.", Value="5_5" }, 
                new SelectListItem { Text="6.0 oz.", Value="6_0" }, 
                new SelectListItem { Text="6.5 oz.", Value="6_5" }, 
                new SelectListItem { Text="7.0 oz.", Value="7_0" }, 
                new SelectListItem { Text="7.5 oz.", Value="7_5" }, 
                new SelectListItem { Text="8.0 oz.", Value="8_0" }, 
                new SelectListItem { Text="8.5 oz.", Value="8_5" }, 
                new SelectListItem { Text="9.0 oz.", Value="9_0" } 
            })
        </fieldset>
    </div>
    <div data-role="fieldcontain" data-inset="true">
        <fieldset data-role="controlgroup">
            <legend>Diaper Details</legend>
            <input id='chkDiaper' name='chkDiaper-1' type="checkbox" class="custom" />
            <label for="chkDiaper">
                Log Diaper</label>
        </fieldset>
        <fieldset data-role="controlgroup">
            <legend>Diaper:</legend>
            @Html.DropDownList("drpDiaper", new List<SelectListItem> {
                new SelectListItem { Text="Wet", Value="wet", Selected=true },
                new SelectListItem { Text="Dirty", Value="dirty" },
                new SelectListItem { Text="Both", Value="both" }
            })
        </fieldset>
    </div>
    <div data-role="fieldcontain" data-inset="true">
        <input id="btnSubmit" type="submit" value="Submit" data-role="button" />
        <fieldset data-role="controlgroup">
            <input id="txtLastEntry" readonly="readonly" type="text" />
        </fieldset>
    </div>
    

    The HTML code builds the input form for entering the feed and diaper change details and the Javascript code collects the input, creates the proxy class and calls its methods to invoke the web service.

    Notice how the @ tag is used to inject runtime variables, such as the logged on user and the base url.

    Home Page view 1
    Home Page view 2
    Keywords: ASP.Net MVC Mobile jQuery Azure
  • ASP.Net MVC4 Mobile Tutorial - Part 2

    Summary

    In the last post, we covered the database design and the Entity model for the sample ASP.Net MVC4 Mobile application. We will continue with the Service layer in this post.


    The Service Layer

    We will define some methods in our service class to enter data into our SQL log tables.

    • Right-click the project, select Add->New Folder and call it Services
    • Right-click the Services folder, select Add, New Item and click on WCF service. Name the service
    • New WCF Service
    • Update the system.serviceModel section in the web.config file so that it looks like the following
    • <system.serviceModel>
          <bindings>
            <webHttpBinding>
              <binding name="customWebHttpBinding">
                <security mode="None"></security>
              </binding>
            </webHttpBinding>
          </bindings>
          <behaviors>
            <endpointBehaviors>
              <behavior name="JSLearning.Services.BabyMonitorServiceBehavior">
                <enableWebScript />
              </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
              <behavior name="DebugBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
              </behavior>
            </serviceBehaviors>
          </behaviors>
          <services>
            <service name="JSLearning.Services.BabyMonitorService" behaviorConfiguration="DebugBehavior">
              <endpoint address="" behaviorConfiguration="JSLearning.Services.BabyMonitorServiceBehavior" binding="webHttpBinding" contract="JSLearning.Services.IBabyMonitorService" bindingConfiguration="customWebHttpBinding" />
              <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            </service>
          </services>
          <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        </system.serviceModel>
    • In the Services folder, add a ServiceBase class and then copy and paste the following code to it. The ServiceBase class provides useful methods for interacting with the data Entity Model
    • public class ServiceBase
          {
              private BabyLogEntities _context = null;
              private string _connectionString = string.Empty;
      
              protected ServiceBase()
              {
                  RenewContext();
              }
      
               protected ServiceBase(string connectionString) {
                   _connectionString = connectionString;
                   _context = new BabyLogEntities(_connectionString);
              }
      
              protected BabyLogEntities Context
              {
                  get
                  {
                      return _context;
                  }
              }
      
              protected void RenewContext()
              {
                   if (_connectionString == string.Empty)
                   {
                       _connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["BabyLogEntities"].ConnectionString;
                   }
                   _context = new BabyLogEntities(_connectionString);
                  return;
              }
      
          }
    • Edit the BabyMonitorService.svc.cs file and have it inherit from ServiceBase.cs
    • public class BabyMonitorService : ServiceBase, IBabyMonitorService
    • Copy and paste the following into your IBabyMonitorService.cs interface
    • [ServiceContract]
          public interface IBabyMonitorService
          {
              [OperationContract]
              [WebMethod]
              [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
              string HeartBeat();
      
              [OperationContract]
              [WebMethod]
              [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
              string AddFeedingEntry(string UserId, string FeedType, string FeedAmount);
      
              [OperationContract]
              [WebMethod]
              [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
              string AddDiaperingEntry(string UserId, string DiaperType);
          }
    • Here is an explanation of the public methods:
      • HeartBeat - is a simple contract to verify that the service is responding
      • AddFeedingEntry - is used to make an entry for a feeding session
      • AddDiaperingEntry - is used to make an entry for a diaper change
    • Open the BabyMonitorService.svc.cs file and add the following code:
    • public class BabyMonitorService : ServiceBase, IBabyMonitorService
          {
              public BabyMonitorService() : base()
              { }
      
              /// <summary>
              /// Check that the service is available
              /// </summary>
              /// <returns></returns>
              public string HeartBeat()
              {
                  return "Service is alive";
              }
      
              /// <summary>
              /// Add a feed entry
              /// </summary>
              /// <param name="UserId"></param>
              /// <param name="FeedType"></param>
              /// <param name="FeedAmount"></param>
              /// <returns></returns>
              public string AddFeedingEntry(string UserId, string FeedType, string FeedAmount)
              {
                  Models.WebServiceResponse response = new Models.WebServiceResponse();
                  try
                  {
                      var log = new FeedingLog
                      {
                          ID = Guid.NewGuid(),
                          DateCreated = DateTime.Now,
                          FeedType = FeedType,
                          // since IIS does not like the . character, we are passing decimals as x_y and converting to x.y
                          FeedAmount = Decimal.Parse(FeedAmount.Replace("_", ".")),
                          UserID = UserId
                      };
      
                      RenewContext();
                      Context.AddToFeedingLogs(log);
                      Context.SaveChanges();
      
                      response.IsSuccess = true;
                  }
                  catch (Exception ex)
                  {
                      response.IsSuccess = false;
                      response.ErrorMessage = ex.Message;
                  }
                  return SerializeAsJSON(response);
              }
      
              /// <summary>
              /// Add an entry for a diaper change
              /// </summary>
              /// <param name="UserId"></param>
              /// <param name="DiaperType"></param>
              /// <returns></returns>
              public string AddDiaperingEntry(string UserId, string DiaperType)
              {
                  Models.WebServiceResponse response = new Models.WebServiceResponse();
                  try
                  {
                      var log = new DiaperLog
                      {
                          ID = Guid.NewGuid(),
                          DateCreated = DateTime.Now,
                          DiaperType = DiaperType,
                          UserID = UserId
                      };
      
                      RenewContext();
                      Context.AddToDiaperLogs(log);
                      Context.SaveChanges();
      
                      response.IsSuccess = true;
                  }
                  catch (Exception ex)
                  {
                      response.IsSuccess = false;
                      response.ErrorMessage = ex.Message;
                  }
                  return SerializeAsJSON(response);
              }
      
              /// <summary>
              /// Serializes an object to JSON
              /// </summary>
              /// <param name="response"></param>
              /// <returns></returns>
              private string SerializeAsJSON(Models.WebServiceResponse response)
              {
                  using (MemoryStream s = new MemoryStream())
                  {
                      DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Models.WebServiceResponse));
                      ser.WriteObject(s, response);
                      s.Position = 0;
                      using (StreamReader sr = new StreamReader(s))
                      {
                          return sr.ReadToEnd();
                      }
                  }
              }
          }
    • The code is quite simple, it uses the Entity Model to make an entry into the respective tables and returns the WebServiceResponse object in JSON format.
    • In the Models folder, add a class called WebServiceResponse and add the following code. The WebServiceResponse is a nice way to return an object as the JSON response, and it can contain a lot of details from the service rather than a simple string error message. Check the service class to see how this object is built.
    • [DataContract]
          public class WebServiceResponse
          {
              /// <summary>
              /// Indicates if the web service call was successful
              /// </summary>
              [DataMember]
              public bool IsSuccess = false;
              /// <summary>
              /// Contains the response message from the service
              /// </summary>
              [DataMember]
              public object Payload = "Object not assigned";
              /// <summary>
              /// Contains a friendly error message if the service encountered an exception
              /// </summary>
              [DataMember]
              public string FriendlyErrorMessage = string.Empty;
              /// <summary>
              /// Contains the full text of the exception, if one occurred
              /// </summary>
              [DataMember]
              public string ErrorMessage = string.Empty;
              /// <summary>
              /// Contains the exception trace, if one occurred
              /// </summary>
              [DataMember]
              public string ErrorStackTrace = string.Empty;
              /// <summary>
              /// Contains the date and time of the service response in UTC format.
              /// </summary>
              [DataMember]
              public string UTC_DateOfResponse = DateTime.Now.ToUniversalTime().ToString("dd MMM yyyy hh:mm:ss tt");
          }
    • At this point we should be able to compile the project and browse to the service. Go to http://yoursite/Services/BabyMonitorService.svc
    • You can also invoke the HeartBeat method from earlier to see if your service is working correctly. Note, you will need to save the JSON response and then open it in notepad to see the results
    • WCF Service Response

    In the next and final post, I will disucss the UI and how it all comes together.


    Keywords: ASP.Net MVC Mobile jQuery Azure
  • ASP.Net MVC4 Mobile Tutorial - Part 1

    Summary

    The ASP.NET MVC 4 Developer Preview introduces also new template for mobile web applications which use jQuery Mobile – a special jQuery library for building mobile user interfaces.

    In this posting I will show you how to build a new mobile web application based on my real world experience of tracking the feeding activities of my 4 month old baby.


    The Design

    We have a 4 month old baby and wanted to keep track of his feeding sessions so we do not wake each other up, especially late at night and to also make sure that the baby was feeding regularly. I have an iPhone, my wife has a HTC phone and we also own a Windows table (running Windows 8 Developer Preview), 2 laptops and a home server/multimedia system. I wanted to write an app for this, but it would be too difficult writing an maintaining an iPhone app, a Metro app and windows applications separately. That's why I decided to write a single web application leveraging the SQL Azure database.

    Getting Started

    You will need one of the following emulators to test the code:

    Building the Solution
    • Install ASP.Net MVC 4 from here
    • Start Visual Studio 2010, choose new Project, then choose Web and select the "ASP.Net MVC 4 Web Application"
    • New MVC Project
    • In the project template box, choose "Mobile Application", leave the View engine as Razor and leave the checkbox for HTML5 semantic markup
    • New MVC Project
    • You will get a default mobile app with forms authentication ready to go

    The Database

    We will need to create a database and the schema for this demo next.

    • On your local instance, create a SQL Server 2008 R2 (SQL 2005+ will do) database and call it BabyLog
    • We need two tables in the database for our application, one to hold records for feeding logs and the other for diaper changes. Run the following SQL to create those
    • CREATE TABLE [dbo].[FeedingLog](
          [ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Log_ID]  DEFAULT (newid()),
          [UserID] [varchar](255) NOT NULL,
          [FeedType] [varchar](255) NOT NULL,
          [FeedAmount] [decimal](18, 1) NOT NULL,
          [DateCreated] [datetime] NOT NULL,
       CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED 
      (
          [ID] ASC
      )WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF)
      )
      GO
    • CREATE TABLE [dbo].[DiaperLog](
          [ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_DiaperLog_ID]  DEFAULT (newid()),
          [UserID] [varchar](255) NOT NULL,
          [DiaperType] [varchar](255) NOT NULL,
          [DateCreated] [datetime] NOT NULL,
       CONSTRAINT [PK_DiaperLog] PRIMARY KEY CLUSTERED 
      (
          [ID] ASC
      )WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF)
      )
      GO
    • Next we need to create tables to support Forms authentication. Open the Visual Studio command prompt and type: aspnet_regsql
    • Register Forms Authentication tables
    • Click next, select "Configure SQL Server for application services", provider the server name, credentials and the database name and click next.
    • Once the wizard finishes, you will see your database tables
    • BabyLog tables

    The Database Model

    Next we will create the Entity Model for our database as well as the WCF uses that our website will use to enter data into the database.

    • In the ASP.Net MVC project, right-click on the Models folder and select "Add New Item"
    • Select the Data template and choose "ADO.Net Entity Data Model
    • Entity Framework Template
    • Select "Generate from Database", then click Next
    • Supply the connection details for your database and name your connection string
    • Select the FeedingLog and DiaperLog tables and leave the Model namespace as BabyLogModel
    • Entity Table Selection
    • You should now have a model with the required tables
    • Database model

    We will look at the service layer in the next post.

    Keywords: ASP.Net MVC Mobile jQuery Azure
  • Get User Profile Owner

    Summary
    Do you need to get the owner of the user profile in SharePoint to conditionally display sensitive data? If yes, then read on... (Tip from colleague Kiran Bellala)


    ProfilePropertyLoader.GetPageProfile method can return the user profile associated with the page.
    (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.portal.webcontrols.profilepropertyloader.getpageprofile.aspx)


    UserProfile thisPageUserProfile = ProfilePropertyLoader.GetPageProfile(this.Page);
    string thisPageAcctName = thisPageUserProfile["AccountName"].Value.ToString();
    string loggedinUserAcctName = HttpContext.Current.User.Identity.Name;            
    if (thisPageAcctName.Equals(loggedinUserAcctName))
    {
          Label1.Text = "This is my user profile";
    }
    else
    {
         //this is not my user profile. hide the web part
         this.Hidden = true;
    }
    
    Keywords: SharePoint User Profile
  • Elmah Exception Logging with Azure

    Summary

    If you have an ASP.Net project mapped to an Azure worker role, then Elmah is a great exception handling framework for providing near code-less, world class exception handling for your project. Read on for a step-by-step guide.


    • Create an Azure web role
    • Reference the Elmah dll in your project
    • In its web.config file, in the configSections node under the configuration node, add the following section:
    • <sectionGroup name="elmah">
            <!-- NOTE! If you are using ASP.NET 1.x then remove the
                requirePermission="false" attribute from the section
                elements below as those are only needed for
                partially trusted applications in ASP.NET 2.0 -->
            <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
            <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
            <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
            <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
            <section name="errorTweet" requirePermission="false" type="Elmah.ErrorTweetSectionHandler, Elmah"/>
      </sectionGroup>
    • Add the elmah node right after configSections
    • <elmah>
      
          <security allowRemoteAccess="1" />
          <errorLog type="Elmah.SqlErrorLog, Elmah"
                  connectionString="data source=server;initial catalog=databaseuser id=user;password=password;multipleactiveresultsets=True;" />
      
          <!--<errorFilter>
            <test>
              <jscript>
                <expression>
                  <![CDATA[
                          // @assembly mscorlib
                          // @assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                          // @import System.IO
                          // @import System.Web
      
                          HttpStatusCode == 404
                          || BaseException instanceof FileNotFoundException 
                          || BaseException instanceof HttpRequestValidationException
                          /* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */
                          || Context.Request.UserAgent.match(/crawler/i)                      
                          || Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only
                          ]]>
                </expression>
              </jscript>
            </test>
          </errorFilter>-->
        </elmah>
    • Under the system.web section add the following modules and handlers
    • <httpHandlers>
            <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
          </httpHandlers>
          <httpModules>
            <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
            <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
            <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
          </httpModules>
    • Under the system.webServer section, add the following modules and handlers
    • <handlers>
            <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" preCondition="integratedMode" type="Elmah.ErrorLogPageFactory, Elmah"/>
          </handlers>
      
          <modules runAllManagedModulesForAllRequests="true">
            <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
            <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
            <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
          </modules>
    • Create the logging table in your database by running the following SQL
    • --~Changing index [dbo].[ELMAH_Error].PK_ELMAH_Error to a clustered index.  You may want to pick a different index to cluster on.
      SET ANSI_NULLS ON
      SET QUOTED_IDENTIFIER ON
      IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_Error]') AND type in (N'U'))
      BEGIN
      CREATE TABLE [dbo].[ELMAH_Error](
          [ErrorId] [uniqueidentifier] NOT NULL,
          [Application] [nvarchar](60) NOT NULL,
          [Host] [nvarchar](50) NOT NULL,
          [Type] [nvarchar](100) NOT NULL,
          [Source] [nvarchar](60) NOT NULL,
          [Message] [nvarchar](500) NOT NULL,
          [User] [nvarchar](50) NOT NULL,
          [StatusCode] [int] NOT NULL,
          [TimeUtc] [datetime] NOT NULL,
          [Sequence] [int] IDENTITY(1,1) NOT NULL,
          [AllXml] [nvarchar](max) NOT NULL,
       CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY CLUSTERED 
      (
          [ErrorId] ASC
      )WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF)
      )
      END
      
      IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_Error]') AND name = N'IX_ELMAH_Error_App_Time_Seq')
      CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_App_Time_Seq] ON [dbo].[ELMAH_Error] 
      (
          [Application] ASC,
          [TimeUtc] DESC,
          [Sequence] DESC
      )WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF)
      GO
      IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF_ELMAH_Error_ErrorId]') AND type = 'D')
      BEGIN
      ALTER TABLE [dbo].[ELMAH_Error] ADD  CONSTRAINT [DF_ELMAH_Error_ErrorId]  DEFAULT (newid()) FOR [ErrorId]
      END
      
      GO
      SET ANSI_NULLS ON
      SET QUOTED_IDENTIFIER ON
      IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_GetErrorsXml]') AND type in (N'P', N'PC'))
      BEGIN
      EXEC dbo.sp_executesql @statement = N'
      CREATE PROCEDURE [dbo].[ELMAH_GetErrorsXml]
      (
          @Application NVARCHAR(60),
          @PageIndex INT = 0,
          @PageSize INT = 15,
          @TotalCount INT OUTPUT
      )
      AS 
      
          SET NOCOUNT ON
      
          DECLARE @FirstTimeUTC DATETIME
          DECLARE @FirstSequence INT
          DECLARE @StartRow INT
          DECLARE @StartRowIndex INT
      
          SELECT 
              @TotalCount = COUNT(1) 
          FROM 
              [ELMAH_Error]
          WHERE 
              [Application] = @Application
      
          -- Get the ID of the first error for the requested page
      
          SET @StartRowIndex = @PageIndex * @PageSize + 1
      
          IF @StartRowIndex <= @TotalCount
          BEGIN
      
              SET ROWCOUNT @StartRowIndex
      
              SELECT  
                  @FirstTimeUTC = [TimeUtc],
                  @FirstSequence = [Sequence]
              FROM 
                  [ELMAH_Error]
              WHERE   
                  [Application] = @Application
              ORDER BY 
                  [TimeUtc] DESC, 
                  [Sequence] DESC
      
          END
          ELSE
          BEGIN
      
              SET @PageSize = 0
      
          END
      
          -- Now set the row count to the requested page size and get
          -- all records below it for the pertaining application.
      
          SET ROWCOUNT @PageSize
      
          SELECT 
              errorId     = [ErrorId], 
              application = [Application],
              host        = [Host], 
              type        = [Type],
              source      = [Source],
              message     = [Message],
              [user]      = [User],
              statusCode  = [StatusCode], 
              time        = CONVERT(VARCHAR(50), [TimeUtc], 126) + ''Z''
          FROM 
              [ELMAH_Error] error
          WHERE
              [Application] = @Application
          AND
              [TimeUtc] <= @FirstTimeUTC
          AND 
              [Sequence] <= @FirstSequence
          ORDER BY
              [TimeUtc] DESC, 
              [Sequence] DESC
          FOR
              XML AUTO
      
      ' 
      END
      GO
      SET ANSI_NULLS ON
      SET QUOTED_IDENTIFIER ON
      IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_GetErrorXml]') AND type in (N'P', N'PC'))
      BEGIN
      EXEC dbo.sp_executesql @statement = N'
      CREATE PROCEDURE [dbo].[ELMAH_GetErrorXml]
      (
          @Application NVARCHAR(60),
          @ErrorId UNIQUEIDENTIFIER
      )
      AS
      
          SET NOCOUNT ON
      
          SELECT 
              [AllXml]
          FROM 
              [ELMAH_Error]
          WHERE
              [ErrorId] = @ErrorId
          AND
              [Application] = @Application
      
      ' 
      END
      GO
      SET ANSI_NULLS ON
      SET QUOTED_IDENTIFIER ON
      IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_LogError]') AND type in (N'P', N'PC'))
      BEGIN
      EXEC dbo.sp_executesql @statement = N'
      CREATE PROCEDURE [dbo].[ELMAH_LogError]
      (
          @ErrorId UNIQUEIDENTIFIER,
          @Application NVARCHAR(60),
          @Host NVARCHAR(30),
          @Type NVARCHAR(100),
          @Source NVARCHAR(60),
          @Message NVARCHAR(500),
          @User NVARCHAR(50),
          @AllXml NVARCHAR(MAX),
          @StatusCode INT,
          @TimeUtc DATETIME
      )
      AS
      
          SET NOCOUNT ON
      
          INSERT
          INTO
              [ELMAH_Error]
              (
                  [ErrorId],
                  [Application],
                  [Host],
                  [Type],
                  [Source],
                  [Message],
                  [User],
                  [AllXml],
                  [StatusCode],
                  [TimeUtc]
              )
          VALUES
              (
                  @ErrorId,
                  @Application,
                  @Host,
                  @Type,
                  @Source,
                  @Message,
                  @User,
                  @AllXml,
                  @StatusCode,
                  @TimeUtc
              )
      
      ' 
      END
      GO
      
    • To test it, go to http://yoursite/elmah.axd


    Keywords: Windows Azure Exception Handling Logging
  • Dynamic Rows to Columns

    Summary

    Do you have a situation where you have data in your table rows that you want to transpose into columns? Furthermore, you are not sure of the number of columns you want to transpose?

    Read on below for a straightforward approach on how to use the Sql Server PIVOT statement combined with dynamic SQL to easily transpose any number of columns.


    Consider that you have a table with a variable number of columns called MyColumn. Then consider a table which has an entry for every column where it links some data to the column.

    Sample Tables to showcase pivot

    You want to transpose the resultset so that the columns in the rows become acutal columns. The trick here is to understand that you will need to build a dynamic query so that you can pass in a variable number of columns.

    Preparation

    -- Create the sample tables
    CREATE TABLE MyColumn([ID] VARCHAR(255), [Name] VARCHAR(255))
    CREATE TABLE MyDynamicData([RowID] INT, [ColumnID] VARCHAR(255), [Data] VARCHAR(255))
    
    -- Create the dynamic columns
    INSERT INTO MyColumn([ID], [Name]) SELECT 'A', 'Column A'
    INSERT INTO MyColumn([ID], [Name]) SELECT 'B', 'Column B'
    INSERT INTO MyColumn([ID], [Name]) SELECT 'C', 'Column C'
    INSERT INTO MyColumn([ID], [Name]) SELECT 'D', 'Column D'
    
    -- Create data which is linked to columns
    DECLARE        @counter INT
    DECLARE @rows INT
    SET @counter = 1
    SET @rows = 1000
    WHILE (@counter < @rows)
    BEGIN
        INSERT INTO MyDynamicData([RowID], [ColumnID], [Data]) SELECT    @counter, 'A', 'Col A Row ' + CAST(@counter AS VARCHAR) + ' Data'
        INSERT INTO MyDynamicData([RowID], [ColumnID], [Data]) SELECT    @counter, 'B', 'Col B Row ' + CAST(@counter AS VARCHAR) + ' Data'
        INSERT INTO MyDynamicData([RowID], [ColumnID], [Data]) SELECT    @counter, 'C', 'Col C Row ' + CAST(@counter AS VARCHAR) + ' Data'
        INSERT INTO MyDynamicData([RowID], [ColumnID], [Data]) SELECT    @counter, 'D', 'Col D Row ' + CAST(@counter AS VARCHAR) + ' Data'
        SET @counter = @counter + 1
    END
    
    SELECT * FROM MyColumn
    SELECT * FROM MyDynamicData 
    
    Pivoting the data

    DECLARE @cols NVARCHAR(2000)
    SELECT  @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
                                    '],[' + [Name]
                            FROM    MyColumn
                            ORDER BY '],[' + [Name]
                            FOR XML PATH('')
                          ), 1, 2, '') + ']'
    
    DECLARE @sql VARCHAR(2000)
    SET @sql = 'SELECT [RowID], ' + @cols +
    ' FROM  
    (
    SELECT A.[RowID], B.[Name], A.[Data]
    FROM MyDynamicData AS A
    INNER JOIN
    MyColumn AS B
    ON A.[ColumnID]=B.[ID]
    GROUP BY A.[RowID], B.[Name], A.[Data]
    ) AS SourceTable
    PIVOT
    (
        MAX([Data])
        FOR [Name] IN (' + @cols + ')
    ) AS PivotTable
    '
    EXEC (@sql)

    The resulting data will be correctly pivoted.

    Data which has been correctly pivoted
    Reference: http://msdn.microsoft.com/en-us/library/ms177410.aspx

    Keywords: SQL Server 2010 2005 PIVOT TRANSPOSE
  • Building an MVC App with Azure

    Summary

    In this article, we will create an deploy an ASP.Net MVC application and deploy it to Azure.

    • Download and install the Visual Studio Azure tools from here
    • Get an Azure account if you do not already have one (optional)
    • Open Visual Studio and choose File –> New –> Project
    • Select “Windows Azure Project”

    SNAGHTML1aa8d728

    • Select ASP.Net MVC 4 Role

    SNAGHTML1aaa0ef9

    image

    • Right-click on MvcWebRole1 and click on Properties

    image

    • In the project settings for WindowsAzureProject1, ensure that “Use the Windows storage emulator” is selected

    image

    • Add a new controller called HomeController to the MVC project

    SNAGHTML1ab77460

    • Add a new folder called Home under the Views folder
    • Add a new view called Index under the home folder

    SNAGHTML1abc8b3a

    • Press F5 to run the application and you should see your test page appear in the Azure emulator

    image

    Keywords: Windows Azure ASP.Net MVC
  • SharePoint and Windows Azure

    Summary

    Learn how to take advantage of Azure features in SharePoint

    There are 3 areas where you can leverage the cloud computing power of Azure:

    • Reach - you can deploy custom WCF services (optionally secured by Access Control Service) to take the burden off your data center. This is especially useful if your application is performing intensive tasks like image processing or transcoding. The same services can be acessed by a variety of devices such as the phone, PC and the Web.
    • Resource - by taking advantage of the CDN, Windows Azure storage (Tables and Blobs) or Sql Azure, you can gain dramatic performance enhancements as well lower storage requirements for your SharePoint assets. A really great product for this is StoragePoint, which leverages the RBS provider to "outsource" storage to Windows Azure BLOB store. More details here. By leveraging remote file storage, such as Windows Azure BLOB storage and data management in SQL Azure, you can reduce resource costs, and at the same time providing greater value to customers with effective solutions.
    • Reusability - you can build one set of services to target multiple devices (web, phone, tablet/pad and PC) and get the maximum value out of your investment

    Click here to download the SharePoint and Windows Azure Development Kit

    Keywords: Microsoft Azure SharePoint 2010
  • Azure Components

    Summary

    The Windows Azure Platform is an application platform in the cloud that allows Microsoft datacenters to host and run applications. It provides a cloud operating system called Windows Azure that serves as a runtime for the applications and provides a set of services that allows development, management and hosting of applications off-premises. All Azure Services and applications built using them run on top of Windows Azure.

    Windows Azure has three core components: Compute, Storage and Fabric. As the names suggest, Compute provides a computation environment with Web Role, Worker Role, and VM Role while Storage focuses on providing scalable storage (Blobs, non-relational Tables, and Queues) for large-scale needs. Relational Database functionality is offered through SQL Azure, which is a scalable version of SQL Server that runs on the Azure platform.

    Azure Platform Components
    • Windows Azure Compute
      • Web Role
      • Worker Role
      • VM Role
    • Windows Azure Storage
      • Table
      • Queue
      • Blob
    • SQL Azure
      • SQL Azure Data Sync
      • SQL Azure Reporting
    • Content Delivery Network
    • Azure AppFabric
      • Access Control
      • Caching
      • Service Bus
    • Windows Azure Fabric Controller
    • Azure Market Place
    • Azure Virtual Network
      • Azure Connect
      • Azure Traffic Manager
    Keywords: Microsoft Azure
  • Windows Storage Emulator Database Issue

    Summary

    When you attempt to launch the Windows Azure storage emulator, you are presented with the following error message: "Failed to initialize Windows Azure storage emulator. See output window for more information"

    The error message in the output window provides more details:

    Windows Azure Tools: Failed to initialize Windows Azure storage emulator. Unable to start Development Storage. Failed to start Development Storage: the SQL Server instance ‘localhost\SQLExpress’ could not be found. Please configure the SQL Server instance for Development Storage using the ‘DSInit’ utility in the Windows Azure SDK.

    This is due to the fact that the Azure Storage Emulator was not able to connect to the database server and create the the required database. To resolve this:

    1. Open the Azure SDK command prompt Azure SDK command prompt
    2. Type the following in the command prompt: dsinit /sqlinstance:InstanceName /user:Domain\User /forceCreate

    The command should execute successfully and the emulator will work. If it fails, double check the value for the SqlInstance parameter.

    Success Keywords: Windows Azure Tools: Failed to initialize Windows Azure storage emulator. Unable to start Development Storage. Failed to start Development Storage: the SQL Server instance ‘localhost\SQLExpress’ could not be found. Please configure the SQL Server instance for Development Storage using the ‘DSInit’ utility in the Windows Azure SDK.
Powered by Community Server (Personal Edition), by Telligent Systems