Saturday, February 11, 2012

Intercept Postbacks

Introduction

Why intercept postbacks? Here is a use case. Your users ask for an Excel-like page to edit multiple records at the same time. No big deal! ISD's EditTable page looks just like an Excel sheet out of the box. You can implement the page in less than 5 minutes with minimal customization. However, there is a tricky issue. If a user pages/sorts/filters the table without saving existing changes, any unsaved changes will lost. It is not an acceptable solution to educate your users to always click the Save button before paging/sorting/filtering. There is no question that you have to save changes automatically. The question is how to implement it.

Brute-Force Implementation

A brute-force implementation is to add code to all event handlers of paging/sorting/filtering. For example,



Repeat this 4 times for PreviousPage, FirstPage, LastPage, and PageSizeButton. There are 10 sortable columns. Repeat 10 more times on the column headers' click event handlers. There are 5 filters above the table control. Repeat another 5 times. Even though you can refactor the try block into a method, so that it is reusable in the event handlers, there are still a lot of boilerplate code.

Better Implementation

A better implementation is to intercept a postback earlier in page load event, and check which control initiates the postback. If it is one of the above mentioned controls, execute SaveData(). Otherwise, return execution to normal life cycle.


Conclusion

If you find yourself doing the same thing again and again in many postback events, try intercepting the postbacks.

Sunday, January 29, 2012

ASP.NET MVC Dynamic Model Binding

Published at: http://dotnetslackers.com/articles/aspnet/ASP-NET-MVC-Dynamic-Model-Binding.aspx

Correction

CustomModelBinder definition:
public class PetBinderAttribute : CustomModelBinderAttribute {

  public override IModelBinder GetBinder() {
    return new PetModelBinder();
  }

  public class PetModelBinder : DefaultModelBinder {
    public override object BindModel(ControllerContext controllerContext, 
      ModelBindingContext bindingContext) {
      var type = controllerContext.HttpContext.Request.Form["PetType"];
      bindingContext.ModelName = type;
      bindingContext.ModelMetadata = ModelMetadataProviders
        .Current.GetMetadataForType(null, petMap[type]);
      return base.BindModel(controllerContext, bindingContext);
    }
    
    static Dictionary<string, Type> petMap = new Dictionary<string, Type>{
      {"Dog", typeof(Dog)},
      {"Cat", typeof(Cat)},
      {"Fish", typeof(Fish)}
    };
  }
}


Use the CustomModelBinder:
[HttpPost]
public ActionResult Create([PetBinder]IPet pet) {
  // BusinessLogic.Save(pet)
  return View();
}

Sunday, December 18, 2011

Re-size and re-center Telerik MVC modal window after ajaxRequest

Telerik MVC modal window can auto-size to fit its initial content. After ajaxRequest, however, the window size stays the same, not adjusting to the new content. Here is how to re-size and re-center a modal window after ajaxRequest. The trick is to remove css "width" and "height" properties from the .t-window-content div.

@{Html.Telerik().Window()
 .Name("Popup")
 .Modal(true)
 .Visible(false)
 .ClientEvents(events => events
  .OnRefresh("resizeOnRefresh")
  .OnResize("centerOnResize"))
 .Render();
}


Saturday, December 17, 2011

Set Min- and Max-Sizes on Telerik ASP.NET MVC Windows

Telerik ASP.NET MVC window (as of 2011.Q3) does not directly support min-length, min-width, max-length or max-width. However, you can set these css properites on its child .t-window-content div. For example,

var winContent = $('#MyWindow .t-window-content');
winContent.css("min-width", "100px");
winContent.css("max-width", "500px");
winContent.css("min-height", "50px");
winContent.css("max-height", "500px");

Thursday, November 17, 2011

OBIEE XMLViewSerive.executeXMLQuery does not accept filters in ReportParams.filterExpressions

OBIEE version:

11.1.1.5.0

Symptom:

I need to evoke XMLViewService.executeXMLQuery() with different saved filters. I tried to set the filter in ReportParams.filterExpressions. The server returned the query result without any complaints. But the results were always the same as the result without any filters.

Work-around:

Set filters directly in ReportRef.

Sunday, November 6, 2011

Bind Telerik MVC TreeView to XElement

In order to bind Telerik MVC TreeView to an XElement, you need to define a recursive function, not a helper. For example,

@using Telerik.Web.Mvc.UI.Fluent;
@using System.Xml.Linq;
@model XElement

@functions {
 void BindXElement(TreeViewItemFactory item, XElement elem){
  var node = item.Add().Text(elem.Name.LocalName);
  foreach (var e in elem.Elements()) {
   node.Items(subItem => BindXElement(subItem, e));
  }
 }
}

@(Html.Telerik().TreeView()
  .Name("TreeView")
  .Items(item => BindXElement(item, Model))
)