In this post, I’ll explain how to pass a model with dynamic objects to a view.

If you are new to C# 4 features like dynamic objects, ExpandoObject etc I suggest to visit below links to get familliar with the concepts.

http://msdn.microsoft.com/en-us/library/dd264741.aspx

http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx

By using dynamic and ExpandoObject, you can pass a runtime object with some dynamic properties to a view and use them efficiently.

Controller Action
——————
——————

 public ActionResult DisplayDynamic()
{
      dynamic obj = new ExpandoObject();
      obj.FirstName = "Raj";
      obj.LastName = "Bandi";
      obj.Country = "Australia";

      return View("DynamicView", obj);
}

DynamicView.cshtml
————————
————————
//here I’m creating a simple view without any layout just to explain how to use the object

@model dynamic

  1. First Name: @Model.FirstName
  2. Last Name: @Model.LastName
  3. Country: @Model.Country

Demo
————–
—————
http://demos.rajbandi.dev/mvc3/home/dynamic

Source Code
————-
————–

http://code.rajbandi.dev/examples/mvc3/mvc3source.zip

In this post, I’ll explain how to post form data without refreshing a page using JQuery ajax and JSON.

Here, I assume a model is used to render form(form elements names same as model properties).

**Step 1:**

Define an action that takes Model as parameter and returns a json object along with attribute HttpPost(simple way)

[HttpPost]
public JsonResult PostMethod(YourModelType m)
{
   // Do something with the model, all the form elements posted are available in the model

   //return json string. Json method that serializes any C# object to json format.
   return Json(your object, JsonRequestBehavior.AllowGet);
}

**Step 2:**

Add javascript function to post data

function PostData(form)
{
  //use only if you wish to validate the form before posting, requires JQuery.validate plugin
 if (!$(form).valid()) {

        return;
    }

    // use $.post, $.ajax can also be used but with some additional parameters
    // 1st parameter is form action to submit, 2nd parameter serialized form data
    // 3rd parameter is the function to be called after successful post and return value
    $.post($(form).attr('action'), $(form).serialize(), function (data) {

           alert('Posted successfully and received data...'+data);


    });
}

Call PostData function to post data on any element action i,e. click etc.

In Sharepoint, SP.UI script namespace provides required methods and classes for showing different types of dialogs.

The following are the list of various dialog methods available under class ModalDialog

1) showModalDialog: To show a modal dialog with some options.

SP.UI.ModalDialog.showModalDialog(options);

2) ShowPopupDialog :

To show a modal dialog with an url and without any options.

3) showWaitScreenSize : this one is used to show a wait screen dialog with a close button

SP.UI.ModalDialog.showWaitScreenSize(title,message,callback,height,width);

for more information on options visit http://msdn.microsoft.com/en-us/library/ff411803.aspx

4) showWaitScreenWithNoClose:

To show a wait screen without any cancel button.

SP.UI.ModalDialog.showWaitScreenWithNoClose(title,message,height,width);

5) commonModalDialogOpen(url,options,callback,args)

To show a modal dialog with url, options, callback, parameters.

SP.UI.ModalDialog.commonModalDialogOpen(url, options, callback, parameters);

ModalDialog class provides other non dialog methods

1) RefreshPage:

SP.UI.ModalDialog.RefreshPage(dialogResult);

2) close:
To close a dialog.
SP.UI.ModalDialog.close(dialogResult);

for showModalDialog and commonModalDialog, there are two ways to pass the options

//generic way

var options = { title: ‘Dialog1’ .height: 300 ,width:300
,url : ‘http://www.rajbandi.dev’
}

//with DialogOptions class

var options = SP.UI.$create_DialogOptions();
options.title = ‘Dialog1’;
options.height = 300;
options.width=300;
options.url = ‘http://www.rajbandi.dev’;

You can also display html string instead of url but have to do in indirect way. Options html property takes a DOM element as an input. When html and url properties are provided, url takes precedence.

var div = document.createElement('div');
div.innerHTML = 'Dialog html demo Dialog html takes an DOM object but not an html string';
var options = {    title: 'Dialog1',
width : 300
,height:300
,html = div
}

To refresh a page after dialog ok clicked.

Sharepoint 2010 provides a custom tag ScriptLink to register script files in a webpart. This can also be done using simple html script tag but using ScriptLink ensures all the sharepoint script namespaces are available for your custom script.

All the scripts that are to be registered should be placed in Layouts/ProjectName folder of your project. By default, when you create a project Layouts folder will not be added.

To add it, right click on your project –> add –> SharePoint “Layouts” Mapped Folder

A default folder with project name will be automatically created under Layouts folder.

Add your custom script files in Layouts/ProjectName/Scripts folder (create Scripts folder if not exist, it can be any name like JS etc.).

Add your code in the script file, here in this example I have added some alert code which is opened by clicking on web part button ‘click here’

Now add ScriptLink tag in your visual web part (i,e. .ascx control)
If you want to do the same in a standard web part, add the below code in OnPreRender method

ScriptLink.register(page,”RajWebPartsDemo/Scripts/RajDemoScript.js”, false);

Deploy your solution and add a your webpart in a page (say home page).

On clicking button ‘Click Here’ an alert is displayed.

JSRender is a jscript template engine very much similar to JQuery templates. It is replacing JQuery templates in the near future and still in beta. The main advantage of any template engine is to reduce the jscript code for rendering dhtml with some data. JSRender can be used with or without using JQuery.

Please visit below link to know more about JSRender

[http://borismoore.github.com/jsrender/demos/index.html](http://borismoore.github.com/jsrender/demos/index.html)

Here, in this example, I will try to explain how you can use Bing Search API to render a search interface with JSRender.

Bing Search API exposes http endpoints that can provide results in XML or JSON. Please visit below link for more information on Bing Search API

[http://www.bing.com/developers/s/APIBasics.html](http://www.bing.com/developers/s/APIBasics.html)

Bing API URL format

**Json**

http://api.bing.net/json.aspx?parameters

**XML**

http://api.bing.net/xml.aspx?parameters

Bing Search API request consists of following required and optional parameters

**Required**

1) AppID : Your site application key provided by Bing.

2) Query: Search text

3) Sources: Web or Images etc..

Optional

1) Web.Offset: Offset 0 means first page

2) Web.Count: Total number of records to be fetched.

>Please note that in order to hide my APPID and misuse, I have installed an application on my server to reverse proxy bing api. What I mean is in the example code there is no direct api calling to bing website but it has to go through my site.

http://bing.rajbandi.dev/search/json.aspx

or

http://bing.rajbandi.dev/search/xml.aspx

All the api requests initiated to my site doesn’t require any APIID but Query and sources parameters are required.

Demo
———-
———

[http://demos.rajbandi.dev/bing/search/jsrender.html](http://demos.rajbandi.dev/bing/search/jsrender.html)

Source
————
————

Access source at JSFiddle.net
[http://jsfiddle.net/rajbandi/7XNbS/](http://jsfiddle.net/rajbandi/7XNbS/)

SSRS Report Viewer control works well in IE6+ but has some known compatibility issues with other major browsers(Firefox, Chrome etc.) around date picker and print button.

For more information read this

http://msdn.microsoft.com/en-us/library/ms251673.aspx

I am presenting a simple solution to fix date picker issue in Chrome with  a combination of some server side code and Client side JQuery script.

 

Server Side Code

 

1) Add the below code in the page/control file in which the reportviewer control resides

 <asp:HiddenField ID="DatePickers" runat="server" />

 

2) Add the below code in the code behind file of page/control in which the reportviewer control resides(.Net 2.0 version)


protected override void OnPreRender(EventArgs e)
{
  base.OnPreRender(e);
  DatePickers.Value = string.Join(",",(new List(GetDateParameters()).ToArray()));
}
private IEnumerable GetDateParameters()
{
  // I'm assuming report view control id as reportViewer
  foreach (ReportParameterInfo info in reportViewer.ServerReport.GetParameters())
  {
    if (info.DataType == ParameterDataType.DateTime)
    {
        yield return string.Format("[{0}]",info.Prompt);
    }
  }
}

 

Client Side Code

 

1) Add the below script in the html head section


$(document).ready(function(){

 if ($.browser.webkit)
 {
    $($(":hidden[id*='DatePickers']").val().split(",")).each(function(i, item){
         var h = $("table[id*='ParametersGrid'] span").filter(function(i) {
             var v = "[" + $(this).text() + "]";
             return (v != null && v.indexOf(item) >= 0);
          }).parent("td").next("td").find("input").datepicker({
           showOn: "button"
           ,buttonImage: '/Reserved.ReportViewerWebControl.axd?OpType=Resource&Name=Microsoft.Reporting.WebForms.calendar.gif'
           ,buttonImageOnly: true
           ,dateFormat: 'dd/mm/yy'
           ,changeMonth: true
           ,changeYear: true
           });
     });
  }

});

 

Hope this helps!!! Smile

When using unobtrusive validation for checkboxes, it does not validate an unchecked checkbox which is marked as required. Its a known issue. By default, all the checkbox required conditions are ignored in unobtrusive validation.

A workaround for this issue is to add a custom attribute and some code change in the unobtrusive JavaScript library.

1. Create a custom attribute

   

    public class RequireCheckedAtrribute : ValidationAttribute, IClientValidatable
    {
        public override bool IsValid(object value)
        {
            return value != null && value is bool && (bool)value;
        }
        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "requirechecked";
            yield return rule;
        }
    }
  
 

2. replace the condition at line 294 in jquery.validate.unobtrusive.js (not minified) with the below lines


var s = $(options.element).attr('data-val-requirechecked');
if (s != null && s != 'undefined')
    options.message = s;
if (options.element.tagName.toUpperCase() !== "INPUT" || !($(options.element).is(':checkbox') &&
(s == null || s == 'undefined'))) {

 

The new code from line 292 looks as below


adapters.add("required", function (options) {
        // jQuery Validate equates "required" with "mandatory" for checkbox elements
        var s = $(options.element).attr('data-val-requirechecked');
        if (s != null && s != 'undefined')
            options.message = s;
        if (options.element.tagName.toUpperCase() !== "INPUT" || !($(options.element).is(':checkbox') &&
(s == null || s == 'undefined'))) {

            setValidationValues(options, "required", true);
        }
    });
 

3. In the model, mark your checkbox field with RequireCheckedAtrribute attribute.

Example:

 
[RequireCheckedAtrribute]
public bool AcceptTerms {get; set;}

 

You can download updated script file from here

 

Happy codingSmile

By default, Report Viewer control displays a default date picker for all the date parameters in parameter section. It creates a hidden iframe for each date picker and a calendar image(input type=’image’) is added next to each date input parameter which act as a trigger for the date picker.

 

ReportViewerDefaultDatepicker_thumb3

There may be a situation when you want to use a JQuery date picker instead of default one. The advantage of  JQuery date picker is in its theme roller and can be displayed with custom theme suited to your application. This can be done by using following script on document ready.


   $(document).ready(function(){
   $("table[id*='ParameterTable'] :input[type='image']").each(function(i)
   {
        var s = $(this).attr("src");
        if (s != null && s.indexOf("calendar") >= 0)
        {
            $(this).hide();
            $(this).prev("input").not(":disabled").datepicker({
                showOn: "button",
                buttonImage: s,
                buttonImageOnly: true,
                dateFormat: 'dd/mm/yy'
                , changeMonth: true
                , changeYear: true
            });//end of date picker
        }
    });//end of each

   });//end of ready

   

After fixing, the new JQuery UI date picker looks like as below

 

ReportViewerJQueryDatepicker_thumb3

Hope this helps Smile

In Chrome browser, Report Viewer (8 & 9) toolbar elements are displayed in multiple rows as shown below.

 

Report ViewerTB1

 

The quick fix for this to change the toolbar table display to ‘inline-block’ when toolbar is displayed. This can be done by applying the following simple Jquery script on document ready. Add css class ‘ms-report-viewer-control’ to your reportviewer control.


$(document).ready(function() {
   if ($.browser.webkit)
   {
	$(".ms-report-viewer-control :nth-child(3) table").each(function(i, item) {
	$(item).css('display', 'inline-block'); });
   }
});

After this fix, the toolbar elements are displayed in a single row

 

Report Viewer TB2

 

Hope this helps Smile

How to download a file with events as like that of Ajax Upload. Its impossible to attach an event before and after a download through javascript. Browser doesn’t allow this type of events for security reasons. Usually a file can be downloaded simply clicking on <A> link pointing to the URL and browser prompts a save dialog to the user.

A file download sometimes may take several minutes, there is no way to display a progress message (ex: downloading.. please wait) to the user like that of Ajax loading (once save dialog displayed , it should be hidden).

I have developed a Javascript plugin and server side code in C#(any language it will work as long as same pattern used) to make this possible. This plugin is entirely developed using MS Ajax code and it well works with other libraries(JQuery etc..). I have used IFrame along with cookies for this.

You’ll require MS Ajax library(MicrosoftAjax.js, go for .Net 3.5 to work with JQuery) to use this plugin(included in the demo) otherwise download it from http://ajax.microsoft.com/ajax/beta/0909/MicrosoftAjax.js

Now I’ll explain how to use this plugin in any page

First of all,  include MS Ajax library(MicrosoftAjax.js) and (MSAjaxDownload.js) in the html head section

<script src="<yourpath>/MicrosoftAjax.js" language="javascript" type="text/javascript" />
<script src="<yourpath>/MSAjaxDownload.js" language="javascript" type="text/javascript" />
 

Now you have to create a simple javascript object  AjaxDownload. Use this object to perform download and attach events. It takes an optional single parameter "download url".

You can use any library on the client side to do this(I have used JQuery in the demo).

var dn = new AjaxDownload(<downloadurl>); // see the default.htm in the demo


The main methods of this object are as listed below (explore source code for other events, I’ll provide documentation soon)


1) add_onBeginDownload : fires before downloading.

   add_onBeginDownload(<javascript method>)

  You can call this method any number of times and attach different methods but they will be executed in the sequence.

2) add_onEndDownload : fires after Save Dialog opens or after an error response.

       add_onEndDownload(<javascript method>)

      You can call this method any number of time to attach multiple events.

3) add_onSuccess : fires after Save Dialog Opens(Successfully received response from server)

4) add_onError :  fires after an error. Error might be on the server or with an invalid url request.

5) EnableTrace : enables tracing to browser javascript console

     EnableTrace(boolvalue)

6) GetParameters : Get the parameters associated with the URL. Return type is always NameValueCollection

7) SetParameters : Set the parameters associated with the URL. Accepts a NameValueCollection object which is defined in the plugin

    SetParameters(namevaluecollection)

8) AddParameter : adds a parameter to the parameter collection

      AddParameter(name)

9)  GetURL : Gets the URL

10) SetURL : Sets the URL

11) GetLastError: Gets the last error occured.

you can attach any javascript method to add_onBeforeDownload, add_onAfterDownload, add_onSuccess, add_onError events(refer MS Ajax handlers).

Example code

 
var dn = new AjaxDownload('http://<serverurl>/');
dn.AddParameter('fileName', 'xyz');
dn.EnableTrace(true);
dn.add_onBeginDownload(beforeDownload);
dn.add_onEndDownload(afterDownload);
dn.add_onSuccess(onSuccess);
dn.add_onError(onError);
function beforeDownload()
{
alert('before download');
}
function afterDownload()
{
alert('after Download');
}
function onSuccess()
{
alert('file download success');
}
funtion onError()
{
var err = dn.GetLastError();
alert('file download error'+err);
}

 

DEMO

I have configured a demo at http://www.rajbandi.dev/Demos/AjaxDownload

 

Download

Files can be downloaded from Microsoft MSDN code library http://code.msdn.microsoft.com/AjaxFileDownload

 

Browsers supported

I have tested in the following browsers and it worked well

a) MSIE(6+)

b) Firefox(3.5)

c) Opera (9)

d) Chrome