Tag Archives: ASP.NET

Easy pattern for Control state

If you have decided that your WebControl requires to maintain it’s state you will want to figure out how to implement Control state. Most examples on the web will then create an array of objects and then hardcode the indices to find stuff back… Simply define a serializable inner class and use that instead of the ‘magic array object’. Eg:

class SilverlightHost : WebControl
{
 [Serializable]
 class State
 {
  public object BaseState { get; set; }
  public string SilverlightUrl { get; set; }
  public string SilverlightErrorHandlerUrl { get; set; }
  public Dictionary<string, string> Parameters { get; set; }
 }

 protected override void OnInit(EventArgs e)
 {
  base.OnInit(e);
  Page.RegisterRequiresControlState(this);
 }

 protected override object SaveControlState()
 {
  var state = new State
  {
   BaseState = base.SaveControlState(),
   SilverlightUrl = SilverlightUrl,
   SilverlightErrorHandlerUrl = SilverlightErrorHandlerUrl,
   Parameters = parameters
  };
  return state;
 }

 protected override void LoadControlState(object savedState)
 {
  var state = (State)savedState;
  SilverlightUrl = state.SilverlightUrl;
  SilverlightErrorHandlerUrl = state.SilverlightErrorHandlerUrl;
  parameters = state.Parameters;
  base.LoadControlState(state.BaseState);
 }
}

Exploring AJAX on the ASP.NET platform

I finally found some time to experiment with AJAX on the ASP.NET platform. The first technique i looked into was Partial-Page Rendering with controls like UpdatePanel. It gave me an awkward feeling but even Dino Esposito, who spent a whole chapter on this technique in his book, seems to share that feeling.

Page methods, public static methods that are decorated with the WebMethodAttribute declared on a Page are exposed as a WebService method and return the result as JSON. An easy solution but it comes with the cost that it does not offer much flexibility.

Thanks to the WebHttpBinding and WebInvokeAttribute the Windows Communication Foundation now supports services that return JSON in a RESTfull call style. This is the technique that i prefer.

jQuery is a very sweet library that simplifies JavaScript development seriously and provides an easy way to consume WCF/JSON services easily. Here is an example of a page with a button that by default triggers a postback (supporting all users, even those without JavaScript) but that behavior is overriden with a XMLHTTP request instead once the document is loaded (an enhancement for users with JavaScript):

$(document).ready(function() {
 $('#RequestEchoButton').click(function() {
  $.ajax({
   type: 'POST',
   url: 'Default.svc/Echo',
   data: '{}',
   contentType: 'application/json; charset=utf-8',
   dataType: 'json',
   success: function(data) {
    $('#EchoResultDiv').html(data);
   },
   error: function(data) {
    $('#EchoResultDiv').html('Failed to request Echo.');
   }
  });
  return false;
 });
});

Notice that my Default.svc page uses the WebServiceHostFactory:

<%@ ServiceHost
 Language="C#"
 Debug="true"
 Service="PageServices.Default"
 Factory="System.ServiceModel.Activation.WebServiceHostFactory"
%>

Conclusion: Unlike jQuery and WCF, I am not convinced that controls like UpdatePanel and ScriptManager add any value to my toolkit.

How does the controller know which action method to invoke?

Yesterday i attended another great VISUG event on ASP.NET presented by Maarten Balliauw. He demonstrated a custom filter but did not dig into the mechanics of action method resolving. With the aid of of the ActionName attribute we can map different methods to the same action. The following methods will all map to the same “Detail” action:

public ActionResult Detail(int productId) { ... }
public ActionResult Detail(int productId, string name) { ... }
[ActionName("Detail")] public ActionResult DisplayDetail(int productId) { ... }
[ActionName("Detail")] public ActionResult ModifyDetail(int productId, string name) { ... }

So how does the Controller know which method to invoke? The answer can be found in the ActionMethodSelector which tries to find the method as following:

public MethodInfo FindActionMethod(ControllerContext controllerContext, string action)
{
 List<methodInfo> methodsMatchingName = GetMatchingAliasedMethods(controllerContext, action);
 methodsMatchingName.AddRange(NonAliasedMethods[action]);
 List<methodInfo> finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);

 switch (finalMethods.Count)
 {
  case 0: return null;
  case 1: return finalMethods[0];
  default: throw CreateAmbiguousMatchException(finalMethods, action);
 }
}

In the RunSelectionFilters method all the found ActionSelection Attributes have their IsValidForRequest method called in the hope that only one potential method remains.

The most common scenario is that we want our controller to behave depending upon the request method (POST vs GET). For this scenario there is the AcceptVerbsAttribute. eg:

[ActionName("Detail")]
[AcceptVerbs("GET")]
public ActionResult DisplayDetail(int productId) { ... }

[ActionName("Detail")]
[AcceptVerbs("POST")]
public ActionResult ModifyDetail(int productId, string name) { ... }

The implementation of the IsValidForRequest method in the AcceptVerbsAttribute is pretty simple:

public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
 if (controllerContext == null) throw new ArgumentNullException("controllerContext");

 string incomingVerb = controllerContext.HttpContext.Request.HttpMethod;
 return Verbs.Contains(incomingVerb, StringComparer.OrdinalIgnoreCase);
}

Adaptive control behavior: LinkButton without javascript

‘Experiment with Adaptive Control Behavior‘ has been an item on my TO-DO list for a very long time and this weekend i finally found some time to do exactly that. Because i hate it that a LinkButton renders as <a href=”javascript:__doPostBackxxx”> i decided to develop a ControlAdapter that makes the LinkButton work without JavaScript. While i was at it i also wrote adapters for the LoginStatus and Login controls. Feel free to play with the Adaptive Rendering Demo.