Friday, March 30, 2012

ASP.NET MVC 3 - Converting / Serializing .Net objects into JSON format in View


In ASP.NET MVC often we might need to use / manipulate Model objects or its property inside the javascript. In order to achieve that, we usually try to serialize the .Net object and store it in a javascript variable which will then be accessed further in javascript.

Using Razor view engine, we can achieve this easily. In the following, I'll explain two approaches with a simple View(.cshtml) snippet to understand the concept. 

Approach 1: (Using Json.Encode(...))

Snippet 1: (Index.cshtml)

@model Web.POC.Models.FeedModel
@{
    ViewBag.Title = "Feed viewer";
}

<script type="text/javascript">
    var entries = @Html.Raw(Json.Encode(Model.FeedEntries));    
</script>


Approach 2: (Using JavaScriptSerializer)

Snippet 2: (Index.cshtml)

@model Web.POC.Models.FeedModel
@{
    ViewBag.Title = "Feed viewer";
}

@{
   System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
}
<script type="text/javascript">
    var entries = @Html.Raw(serializer.Serialize(Model.FeedEntries));    
</script>


Assumptions:

As specified, the above snippets are just to understand the concept. In that, consider that we're having a model "FeedModel" which holds a property called "FeedEntries" of some custom type which we're trying to convert into JSON object.

Also note that we need to use the HTML.Raw() to indicate that the output should not be HTML encoded.


Monday, March 12, 2012

ASP.NET - Avoid multiple postbacks for control set using validators by disabling the button


In ASP.NET disabling the button when a postback got initiated through button click and avoiding multiple postbacks or submits until the specific response is processed is one of the common thing that we need to implement. This is especially  needed for some long running operations. During my initial days, I achieve this as specified here. Later, I followed as specified here in an article by Abhijit Jana. Few days back one of my friend asked me about how to disbale the button to avoid multiple submits / postbacks for control set that are using ASP.NET validation. To achieve that, I tried a sample and came up with two approaches.

Let us consider a scenario that we have a text box, a required field validator and button tied together using validation group.

Approach 1: (Using jQuery and a button proxy)

  • Apply CSS style="display:none;"  to the button you want to disable.
  • Include a new button for display purpose and add a jQuery that validates the validation group using the function Page_ClientValidate() passing the validationgroup as parameter. 
  • Based on the return value of Page_ClientValidate(), raise the click event of the hidden button using jQuery and disable the display button. 
The following script snippet helps us to achieve that.

Snippet 1:(script)

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

    function initAction() {
        $('#Button2').click(function (event) {
            event.preventDefault();

            if (Page_ClientValidate('ValGroup1')) {
                this.disabled = true;
                $('#Button1').click();
            }

        });
    }
</script>


Here is the full implementation of the same.

Snippet 2:(DisableButtonOnClickApp1.aspx)

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DisableButtonOnClickApp1.aspx.cs"
    Inherits="DisableButtonOnClickApp1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            initAction();
        });

        function initAction() {
            $('#Button2').click(function (event) {
                event.preventDefault();

                if (Page_ClientValidate('ValGroup1')) {
                    this.disabled = true;
                    $('#Button1').click();
                }

            });
        }
    </script>

</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td>
                    <asp:Label ID="Label1" runat="server" Text="Label 1 : "></asp:Label>
                </td>
                <td>
                    <asp:TextBox ID="TextBox1" runat="server" ValidationGroup="ValGroup1"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator"
                        ControlToValidate="TextBox1" ValidationGroup="ValGroup1"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td colspan="2" style="text-align: center;">
                    <asp:Button ID="Button1" runat="server" Text="Hide Button" Style="display: none;"
                        ValidationGroup="ValGroup1" onclick="Button1_Click" />
                    <asp:Button ID="Button2" runat="server" Text="Display Button" />
                </td>
            </tr>
            <tr>
            <td colspan="2" style="text-align: center;">
                <asp:Label ID="StatusMessageLabel" runat="server" Text=""></asp:Label>
            </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>


Snippet 3:(DisableButtonOnClickApp1.aspx.cs)

public partial class DisableButtonOnClickApp1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        StatusMessageLabel.Text = "Button 1 click .......";
    }
}


If you are not much interested in using one additional control to achieve this, the following approach might help you.

Approach 2: (Using GetPostBackEventReference with PostBackOptions and UseSubmitBehavior)

The idea for this approach evolved from the article I specified above. Following snippets helps you to understand the implementation easily. Here we're going to use ClientScript.GetPostBackEventReference with PostBackOptions and Button.UseSubmitBehavior to achieve the resultant.

Snippet 4: (DisableButtonOnClickApp2.aspx.cs)

public partial class DisableButtonOnClickApp2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DisableButtonOnClick(Button1, "ValGroup1");
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        StatusMessageLabel.Text = "button 1 click......";
    }

    private void DisableButtonOnClick(Button buttonControl, string validationGroup)
    {
        StringBuilder disableButtonScriptBuilder = new StringBuilder();
        PostBackOptions postBackOptions = new PostBackOptions(buttonControl);

        postBackOptions.ValidationGroup = validationGroup;
        postBackOptions.Argument = "";
        postBackOptions.PerformValidation = true;
        postBackOptions.ActionUrl = "";
        postBackOptions.TrackFocus = false;
        postBackOptions.ClientSubmit = false;
        postBackOptions.RequiresJavaScriptProtocol = true;

        disableButtonScriptBuilder.Append(ClientScript.GetPostBackEventReference(postBackOptions, false));
        disableButtonScriptBuilder.Append("; if(Page_ClientValidate('");
        disableButtonScriptBuilder.Append(validationGroup);
        disableButtonScriptBuilder.Append("')){this.value='Processing...';this.disabled = true;}");

        //buttonControl.OnClientClick = ClientScript.GetPostBackEventReference(postBackOptions, false) + "; if(Page_ClientValidate('" + validationGroup + "')){this.value='Processing...';this.disabled = true;}";
        buttonControl.OnClientClick = disableButtonScriptBuilder.ToString();
        buttonControl.UseSubmitBehavior = false;
    }
}

Snippet 5: (DisableButtonOnClickApp2.aspx)

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DisableButtonOnClickApp2.aspx.cs" Inherits="DisableButtonOnClickApp2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <table border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td>
                    <asp:Label ID="Label1" runat="server" Text="Label 1 : "></asp:Label>
                </td>
                <td>
                    <asp:TextBox ID="TextBox1" runat="server" ValidationGroup="ValGroup1"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator"
                        ControlToValidate="TextBox1" ValidationGroup="ValGroup1"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td colspan="2" style="text-align: center;">
                    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
                </td>
            </tr>
            <tr>
            <td colspan="2" style="text-align: center;">
                <asp:Label ID="StatusMessageLabel" runat="server" Text=""></asp:Label>
            </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>


Based on your comfort, use any of the above two approaches.

Thursday, February 23, 2012

Unauthorized access exception when value set for property using Secondary Thread - Silverlight

Thinking about threading in Silverlight 4, we choose between the two options
  1. Background worker
  2. Managing thread manually
Most of the time-consuming operations will be handled using the Background worker without blocking the UI. It ultimately executes in a separate thread. The main functions and events to know in Background worker are DoWork, RunWorkerCompleted and RunWorkerAsync. As the name specifies we need to add the event handler for DoWork event for doing the background operation. Add the handler for RunWorkerCompleted to receive the operation completed notification.  RunWorkerAsync method is to start the operation. The main thing to note is that we should not access directly access the UI objects from the DoWork event.

Also there are times where we need to manage the threads manually. Since Silverlight runs in a Single threaded apartment (STA) application model and the default is the UI thread, accessing the UI objects from other thread leads to cross thread exception. Knowing this fact I worked with a secondary thread and updated a property in my ViewModel. In that scenario I got an exception and digging into the inner exception found out the cross thread exception. For understanding I've created a sample scenario that raises exception.

Snippet 1

public partial class ThreadTest : UserControl, INotifyPropertyChanged
{        
    private string textValue;
    public string TextValue
    {
        get { return textValue; }
        set
        {
            textValue = value;
            NotifyPropertyChanged("TextValue");
        }
    }

    public ThreadTest()
    {
        InitializeComponent();

        InitControls();
    }

    private void InitControls()
    {
        this.DataContext = this;
    }

    private void Direct_Click(object sender, RoutedEventArgs e)
    {
        TextValue = "direct text......";
    }

    private void UsingTask_Click(object sender, RoutedEventArgs e)
    {
        Thread secondaryThread = new Thread(SecondaryThreadWorker);
        secondaryThread.Start();
        
    }

    private void SecondaryThreadWorker()
    {
        TextValue = "thread text.......";            
    }


    #region INotifyPropertyChanged Members

    protected void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

Then examining the cause, realized that the specific property raises an property changed notification . Immediately recalled the excellent article from Pete Brown in his 10rem.net blog.

The following implementation does the trick.

Snippet 2 (Just replace the INotifyPropertyChanged implementation)

#region INotifyPropertyChanged Members

protected void NotifyPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        if (Deployment.Current.Dispatcher.CheckAccess())
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        else
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            });
        }
    }
}

public event PropertyChangedEventHandler PropertyChanged;

#endregion


When I typed "Deployment.Current.Dispatcher.", it didn't show up the "CheckAccess()" method in the intellisense. But I verified it in the object which shows the existence of the method. So I manually typed the  "CheckAccess()" method name and got complied without error.

References
http://10rem.net/blog/2012/01/10/threading-considerations-for-binding-and-change-notification-in-silverlight-5




Monday, February 6, 2012

ASP.NET MVC 3 - Accessing Session inside Task of AsyncController

Before getting into the core of this post, let us have a quick look at Async controller. The base thing that we need to understand is that, Async controllers are implemented to achieve the efficient service of the incoming requests rather than faster processing of individual request. Scenarios like the case of having a network call which consumes some time might block the thread (that is processing the current request) from processing other requests. For understanding the need for using the AsyncController, there exists several articles over the web. One such nicely explained article is here.

In order to implement the Async controller, we need to do the following.
Derive the controller from AsyncController. 
Specify an <ActionName>Async and <ActionName>Completed methods for each Actions, where <ActionName>Async is of return type void and the relevant <ActionName>Completed returns the ActionResult.
Usually the network calls will be made in the <ActionName>Async method and the resultant is passed over to the <ActionName>Completed method as arguments.

Above specified info are fine enough to implement the Async controller. Apart from that, we also need to think of effectively handling the network calls and other time consuming items inside the <ActionName>Async method. In real case, usually we'll call the method in Model / ViewModel which then initiates the network call,  call to the Service Locator or Service Agent. For achieving this, we can alter the Model / ViewModel to expose the relevant methods async mode. Instead we can also seek help from the .Net built in library named Task Parallel Library (TPL). Instead of explaining further, I directly dive into the code sample from which you can easily understand the base.

Snippet 1:

public void IndexAsync(int id)
{
    AsyncManager.OutstandingOperations.Increment();

    Task.Factory.StartNew(() => {
        InfoViewModel moreViewModel = new InfoViewModel();
        InfoViewModel.MoreModel moreModel = moreViewModel.GetDetails(id);

        AsyncManager.Parameters["moreModel"] = moreModel;
        AsyncManager.OutstandingOperations.Decrement();
    });
    
}

public ActionResult IndexCompleted(InfoViewModel.MoreModel moreModel)
{
    return View("Info", moreModel);
}

The AsyncManager related operations specified in the above code helps us to achieve handling of  aysnc operations effectively. For example, the Increment(), Decrement() methods and Parameters property helps the controller to identify, when to make the call to relevant <ActionName>Completed method with specific parameters. As you guess, the Task.Factory.StartNew(Action) will be executed in a separate thread and in the mean time, statements following it got executed and waits until the AsyncManager.OutstandingOperations becomes zero after which <ActionName>Completed gets called.

OK, now comes the core of the post. Think of a situation where we need to use access the Session values inside the method of Model / ViewModel which is initiated from Task.Factory.StartNew(Action).  Since the Task is executed in a separate thread, that thread won't hold the HttpContext that is System.Web.HttpContext.Current will be null. To make it work, we can assign the System.Web.HttpContext.Current with the HttpContext got from ControllerContext as follows.

Snippet 2:

System.Web.HttpContext.Current = ControllerContext.HttpContext.ApplicationInstance.Context;


Please note that the above specified fix is just a workaround. For such scenarios, we need to alter the method in the Model in such a way to receive the value retrieved from session as one of the parameter. 

As we might use this repeatedly, we can create a base class and make use it in places wherever required.

Snippet 3: (BaseAsyncController) 

public class BaseAsyncController : AsyncController
{
    protected void StartContextEnabledTask(Action action)
    {
        Task.Factory.StartNew(() => {
            System.Web.HttpContext.Current = ControllerContext.HttpContext.ApplicationInstance.Context;
            action();
        });
    }
}

Snippet 4: (Full Implementation)

public class InfoController : BaseAsyncController
{
    public void IndexAsync(int id)
    {
        AsyncManager.OutstandingOperations.Increment();
    
        StartContextEnabledTask(() => {
            InfoViewModel moreViewModel = new InfoViewModel();
            InfoViewModel.MoreModel moreModel = moreViewModel.GetDetails(id);
    
            AsyncManager.Parameters["moreModel"] = moreModel;
            AsyncManager.OutstandingOperations.Decrement();
        });
        
    }
    
    public ActionResult IndexCompleted(InfoViewModel.MoreModel moreModel)
    {
        return View("Info", moreModel);
    }    
}

References:
http://www.aaronstannard.com/post/2011/01/06/asynchonrous-controllers-ASPNET-mvc.aspx
http://msdn.microsoft.com/en-us/library/dd537609.aspx
http://craigcav.wordpress.com/2010/12/23/asynchronous-mvc-using-the-task-parallel-library/

Wednesday, December 21, 2011

Upgrading Nuget 1.5 to 1.6 - Installation error

If you have the Nuget 1.5 extension installed, your Visual Studio (VS 2010) will prompt to update to Nuget 1.6 version. If you try to update to Nuget 1.6, you might run into installation error. If so, uninstall the older version - Nuget 1.5 and then try installing the new version - Nuget 1.6. In order to uninstall Nuget, you need to run the VS 2010 in "administrator" mode.


For more details view the release notes here.

Monday, December 19, 2011

C# extension method - OrderBy sort expression as string

Recently I came across a question in a forum where a part of the solution requires the sort expression as string type for the OrderBy extension method. The requirement is, upon passing a string of property name separated by comma, the respective sort need to be applied and returned.

Without explaining further, directly I dive into the implementation so that you can easily infer from that. I altered the snippet got from http://www.extensionmethod.net/Details.aspx?ID=124 based on our needs.

Snippet 1 (Core extension method for OrderBy and ThenBy)

public static class IEnumerableExtensions
{
    public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
    {
        sortExpression += "";
        string[] parts = sortExpression.Split(' ');
        bool descending = false;
        string property = "";

        if (!(parts.Length > 0 && parts[0] != ""))
        {
            throw new Exception("Invalid sort expression.");
        }

        property = parts[0];

        if (parts.Length > 1)
        {
            descending = parts[1].ToLower().Contains("esc");
        }

        PropertyInfo prop = typeof(T).GetProperty(property);

        if (prop == null)
        {
            throw new Exception("No property '" + property + "' in + " + typeof(T).Name + "'");
        }

        if (descending)
            return list.OrderByDescending(x => prop.GetValue(x, null));
        else
            return list.OrderBy(x => prop.GetValue(x, null));
    }

    public static IOrderedEnumerable<T> ThenBy<T>(this IOrderedEnumerable<T> list, string sortExpression)
    {
        sortExpression += "";
        string[] parts = sortExpression.Split(' ');
        bool descending = false;
        string property = "";

        if (!(parts.Length > 0 && parts[0] != ""))
        {
            throw new Exception("Invalid sort expression.");
        }

        property = parts[0];

        if (parts.Length > 1)
        {
            descending = parts[1].ToLower().Contains("esc");
        }

        PropertyInfo prop = typeof(T).GetProperty(property);

        if (prop == null)
        {
            throw new Exception("No property '" + property + "' in + " + typeof(T).Name + "'");
        }

        if (descending)
            return list.ThenByDescending(x => prop.GetValue(x, null));
        else
            return list.ThenBy(x => prop.GetValue(x, null));
    }

    public static IEnumerable<T> OrderByStringExpression<T>(this IEnumerable<T> queryObj, string orderByProperties)
    {
        if (string.IsNullOrWhiteSpace(orderByProperties))
        {
            //throw new Exception("Invalid sort expression");
            return queryObj;
        }

        string[] orderByPropertyArray = orderByProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        IOrderedEnumerable<T> orderedItem = null;

        if (orderByPropertyArray.Length > 0)
        {
            orderedItem = queryObj.OrderBy(orderByPropertyArray[0]);

            if (orderByPropertyArray.Length > 1)
            {
                for (int i = 1; i < orderByPropertyArray.Length; i++)
                {
                    orderedItem = orderedItem.ThenBy(orderByPropertyArray[i]);
                }

            }
        }

        return orderedItem;
    }
}

Snippet 2 (Example code)

var sortResult = listInst.OrderByStringExpression("Id,Name desc");

As you see, each property name should be separated by comma and if required you can specify the sort mode (asc/desc) followed by a blank space with the respective parameter.

Now with the above specified method, we can pass simple comma separated string as sort expression and get the related instance sorted. This will helpful in scenarios like implementing the Repository pattern as I did here.  Hope this helps.

References
http://www.extensionmethod.net/Details.aspx?ID=124





Sunday, December 4, 2011

Windows Phone 7.1 - Things to know about Dormant and Tombstone states

In WP 7.1, if we click on the start button when an application is running, the application will have the Deactivated event got fired. Usually developers will save any application state in this event handler into the application level dictionary object represented through the PhoneApplicationService.State property and make use of it in the Activated state again.

After the Deactivated event got invoked, the application which is in running state is moved to the Dormant state. Most developers get this state unnoticed. In this Dormant state, application still remain in memory but without processing happen and without application getting terminated. Based on the memory resource requirements for other applications, the application in the Dormant state has the possibility to get into the Tombstone state. The Tombstone state for an application represents the application as terminated, in the meantime, it holds the state info of the application. By state info we mean, the application state which is represented through the PhoneApplicationService.State property (as specified above) and the page state which is represented through PhoneApplicationPage.State property.

The main thing we need to notice is the reactivation scenario of an application. The application might get  reactivated from both the states directly. In both the cases, it raises the Activated event, where we need to identify whether the application is activated from the Tombstone state. If so, we can get values from the application level state dictionary (PhoneApplicationService.State) and make use of it. If it was from Dormant state, we don't need to do anything as the OS automatically preserves the state.

Since both scenarios raises the Activated event, there needs to be a mechanism to identify whether the immediate previous state is Dormant or Tombstone state. It is the IsApplicationInstancePreserved property of the ActivatedEventArgs which helps us to achieve this. As you might guess, if the IsApplicationInstancePreserved is true then it was from Dormant state and if it is false, then it was form Tombstone state.

While debugging your application you can validate both these Dormant and Tombstone state scenarios by clicking on the start button of your emulator when your application is running . When you click on the start button of the emulator, by default, the application will move to the Dormant state. If you want to validate the Tombstone state, check the "Tombstone upon deactivation while debugging" check box in the Debug tab of the project properties.

Following snippet helps you to understand handling of Dormant and Tombstone states:

Snippet 1 (App.xaml.cs)

private void Application_Launching(object sender, LaunchingEventArgs e)
{
    Debug.WriteLine("Application launching event");
}

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    Debug.WriteLine("Application activated event");
    
    if (e.IsApplicationInstancePreserved)
    {
        Debug.WriteLine("Application activated from Dormant state....");
    }
    else
    {
        Debug.WriteLine("Application activated from Tombstone state.....");
    }
}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    Debug.WriteLine("Application deactivated event");
}

private void Application_Closing(object sender, ClosingEventArgs e)
{
    Debug.WriteLine("Application closing event");
}

Creative Commons License
This work by Tito is licensed under a Creative Commons Attribution 3.0 Unported License.