Showing posts with label ASP.NET MVC. Show all posts
Showing posts with label ASP.NET MVC. Show all posts

Monday, 11 February 2013

jQuery ajax success callback not firing

A form that uses jQuery to call a JSON returning action to populate a dependent dropdown on the change event of another dropdown no longer worked when the script registration changed to 1.4.4. It had been working previously with jQuery 1.6.4. (This would also apply to porting apparently working code to a new ASP.NET MVC 3 with earlier jQuery version.)

Having established that the success callback was no longer being fired, I added an alert to the error callback and found that the ajax call was generating the error "jQuery#####.##### was not called" (with some random numbers). This error is thrown when the ajax call parses the data returned by the URL (action) and determines that it is malformed according to the dataType property of the settings object parameter (in this case 'json'). jQuery 1.4.x is stricter than subsequent versions when parsing JSON, and the ajax call will throw the parse error if the JSON is not properly formatted - see jQuery API.

The MVC action returning JSON data contained the following line:

return Json((from r in roles select new { Value = r.Id.ToString(), Text = r.Title }).ToArray());

It looks like when MVC returns a JsonResult containing an array, the array is deemed by jQuery 1.4.x to be not properly formatted according to the JSON specification! Version 1.6.x masks this problem, otherwise for 1.4.x changing the dataType property of the settings object parameter of the ajax call from 'json' to 'text json' allows the call to succeed.

Monday, 12 December 2011

How to force view compilation in an ASP.NET MVC project

When you build an ASP.NET MVC project, the default behaviour is to exclude view files from compilation. To include views unload the project (in Solution Explorer right click the project and select Unload Project) and edit the project file (right click the project node and select Edit <project name>.csproj).  Locate the MvcBuildViews setting and change this to true.  On reloading the project, building will now compile all views.

Note that this will include all view files in the project's Views folder on disk, even if these are not added to the project.

Tuesday, 4 October 2011

Using the ASP.NET membership provider in an MVC controller

You can refer to the default ASP.NET membership provider in the controller action using the Membership.Provider object, just as in ASP.NET Web Forms. This is because ASP.NET MVC uses the same ASP.NET infrastructure as Web Forms. This is how the default AccountController, built when you select the ASP.NET MVC 3 Internet Application template, provides authentication functionality. It declares an IMembershipService interface dependency, to abstract the authentication functionality, and instantiates this with the AccountMembershipService concrete class in the controller’s Initialize method:

public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
    if (FormsService == null) { FormsService = new
    FormsAuthenticationService(); }
    if (MembershipService == null) { MembershipService = new
    AccountMembershipService(); }

    base.Initialize(requestContext);
}


The IMembershipService interface and AccountMembershipService implementation are in the AccountModels file.

Of course you can check whether the current identity is authorized without having to directly use the Membership.Provider object, by using the AuthorizeAttribute attribute.

[Authorize]
public ActionResult About()
{
    return View();
}


Adding this attribute to the action method declaration will make the MVC runtime check whether the identity is authenticated. If the identity is not authenticated, the runtime will throw a SecurityException exception.

Tuesday, 13 September 2011

Getting AjaxLink to work in MVC 3

In a master/detail scenario, I had a view listing master items with a details link for each item. I wanted the details link to display child details using AJAX.

To do this you need the Ajax.ActionLink helper method. This takes (among other overloads) the following form:

@Ajax.ActionLink("Details", "Details", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divDetails" })

Here we are specifying the link text, the controller action, the route value and the target HTML element to update with the result of the Ajax request.

The Details action should return a PartialResult.

I had trouble getting this to work, as the Details action just posted back to a new page instead of the target element. Eventually I discovered that the key to getting this working is to add the following script (in _Layout.cshtml):

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>

Tuesday, 15 February 2011

How to display a jQuery datepicker control in an ASP.NET MVC partial view

When trying to use the jQuery datepicker in an ASP.NET MVC partial view I found that the calendar didn't display correctly.  On investigating the problen I realized I was calling the datepicker function in the wrong place.  Calling it in the partial view doesn't work - the MVC framework ignores the script when it renders the partial view in the .aspx view.  Calling it in the .aspx view's document ready event doesn't work either because at this stage it doesn't know about the control.

Here's a way to get it working.

Firstly, link the jQuery UI CSS file in the head section of the master file:

<link type="text/css" href="../../Content/jquery-ui-1.8.9.custom.css" rel="stylesheet" />

Add the jQuery script references to the head section of the master file (or in the appropriate asp:Content section in the .aspx view in which you're posting the partial view):

<script type="text/javascript" src="../../Scripts/jquery-1.4.1.js"></script>
<script type="text/javascript" src="../../Scripts/jquery-ui-1.8.9.custom.min.js"></script>

Create a Javascript function that calls the datepicker function:

<script type="text/javascript">
    function showDatePicker() {
        $('#date').datepicker();
    }
</script>

Declare the input element in the partial view, making sure to give it the same id you used in the call to datepicker:

<input type="text" name="date" id="date" />

Finally (this is the crucial bit), you need to call this function in the OnSuccess parameter of the Ajax call in the .aspx view, e.g.:

<li><%= Ajax.ActionLink("Some text to click on", "action_name", new { Id = Model.Id }, new AjaxOptions { OnSuccess = "showDatePicker", UpdateTargetId = "div_name" })%></li>

Note that this doesn't work if you use the OnComplete parameter.