0

My Data appears in IE like

[{"UserId":1,"Surname":"Scccce","Forename":"John","Pax":"0777533303","Mobile":"07775803803","Email":"john803.......

When I want the Javascript to fire and create a grid...

My Controller Code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using Emas.Model;
using Emas.Web.Models.Repositories;
using Emas.Web.Models.FormViewModels;
using Emas.Web.Helpers;
using Emas.Web.Extentions;
using System.Web.Script.Serialization;

namespace Emas.Web.Controllers
{


    [Emas.Web.Helpers.AuthorizeHelpers.EMASAuthorize]

    public class UserController : Controller
    {
        private EmasDataContext _db = new EmasDataContext();
        private SecurityRepository _securityRepository = new SecurityRepository();

        #region Index

        public ActionResult Index()
        {
            //if (!User.IsInRole("Active"))
            //    return View("NotAuthorised");

            if (!User.IsInRole("Admin")) // Only ADMIN users can setup user access and roles
                return View("NotAuthorised");

            var allUsers = _securityRepository.FindAllUsers();

            if (allUsers == null)
                return View("NotFound");

            return View(allUsers);           
        }

        public JsonResult IndexJSon()
        {
            //if (!User.IsInRole("Active"))
            //    return View("NotAuthorised");

            //var allUsers = _securityRepository.FindAllUsers();
            //return this.Json(allUsers);

            var results = from user in _db.aspnet_Users
                          select new
                          {
                              UserId = user.UserId,
                              Surname = user.Surname,
                              Forename = user.Forename,
                              Pax = user.Pax,
                              Mobile = user.Mobile,
                              Email = user.Email,
                              Active = user.Active,
                              UserName = user.UserName
                          };

            return Json(results);
        }

        public JsonResult Index2()
        {


            var results = from user in _db.aspnet_Users
                          select new
                          {
                              UserId = user.UserId,
                              Surname = user.Surname,
                              Forename = user.Forename,
                              Pax = user.Pax,
                              Mobile = user.Mobile,
                              Email = user.Email,
                              Active = user.Active,
                              UserName = user.UserName
                          };

            return this.Json(results, "text/html");

        }

        #endregion Index

        #region Details

        public ActionResult Details(int id)
        {
            aspnet_User user = _securityRepository.GetUser(id);

            if (user == null)
                return View("NotFound");

            return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));
        }

        #endregion Details

        #region Delete
        [AcceptVerbs(HttpVerbs.Delete)]
        public void Delete(int id, string ConfirmButtons)
        {
            aspnet_User user = _securityRepository.GetUser(id);
            this._securityRepository.Delete(user);
            this._securityRepository.Save(User.Identity.Name);
        }
        #endregion Delete

        #region Create

        // GET:
        public ActionResult Create()
        {
            aspnet_User user = new aspnet_User();
            return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));
        }

        // POST: 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(aspnet_User user, string[] Roles)
        {
            if (user.UserName != null)
                user.LoweredUserName = user.UserName.ToLower();

            //TODO dc - hardcoded for demo - fix
            user.ApplicationId = new Guid("311566ad-a279-4d0b-a883-89425bdc69e3");
            _securityRepository.Add(user);


            if (Roles == null)
            {
                //ModelState.AddModelError("User In Roles", "You must select at least one Role for this user to be in.");
                //Code Removed during UAT, being in no Roles implies READ ONLY user
            }
            else
            {
                foreach (string role in Roles)
                {
                    aspnet_UsersInRole userInRole = new aspnet_UsersInRole()
                    {
                        //RoleId = new Guid(role), GUID removed
                        UserId = user.UserId

                    };
                    user.aspnet_UsersInRoles.Add(userInRole);
                }
            }

            if (!ModelState.IsValid)
                return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));

            this._securityRepository.Save(User.Identity.Name);
            return RedirectToAction("Index", new { id = user.UserId });
        }

        #endregion Create

        #region Edit

        // GET: 
        public ActionResult Edit(int id)
        {
            aspnet_User user = _securityRepository.GetUser(id);


            if (user == null)
                return View("NotFound");           

            return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(),this._securityRepository.FindAllUsers()));
        }

        // POST: 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, string[] Roles)
        {
            aspnet_User user = _securityRepository.GetUser(id);
            _securityRepository.DeleteUserInRoles(user);

            if (Roles == null)
            {
                //ModelState.AddModelError("User In Roles", "You must select at least one Role for this user to be in.");
                //Code Removed during UAT, being in no Roles implies READ ONLY user
            }
            else
            {                              
                foreach (string role in Roles)
                {
                    aspnet_UsersInRole userInRole = new aspnet_UsersInRole()
                    {
                        //RoleId = new Guid(role),
                        UserId = user.UserId
                    };
                    user.aspnet_UsersInRoles.Add(userInRole);
                }                
            }

            TryUpdateModel(user);
            if (!ModelState.IsValid)
                return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));

            this._securityRepository.Save(User.Identity.Name);
            return RedirectToAction("Index");
        }

        public ActionResult ReassignActions(int id)
        {
            aspnet_User user = _securityRepository.GetUser(id);

            if (user == null)
                return View("NotFound");

            return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));
        }

        // POST: 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ReassignActions(int id, string[] Roles,Guid UserLoginId)
        {
            if (!User.IsInRole("Admin")) // If Admin user then block from EDITING
                return View("NotAuthorised");

            aspnet_User user = _securityRepository.GetUser(id);

            //this._db.ReassignUserScheduledActions(user.UserId.ToString(), UserLoginId.ToString());

            return View(new UserFormViewModel(user, this._securityRepository.FindAllRoles(), this._securityRepository.FindAllUsers()));

        }

        #endregion Edit                               
    }
}

My index2.aspx is:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="application/json; charset=utf-8" />
<title>My First Grid</title>

<link type="text/css" href="~/Content/jQueryUI/css/jquery-ui-1.8.11.custom.css" rel="stylesheet" />
<link href="~/Content/jquery-1/css/ui.jqgrid.css" rel="stylesheet" type="text/css" />

<style type="text/css">
html, body {
    margin: 0;
    padding: 0;
    font-size: 75%;
}
</style>

<script src="~/Scripts/jquery-1.5.2.js" type="text/javascript"></script>
<script src="~/Content/jquery-1/js/grid.locale-en.js" type="text/javascript"></script>
<script src="~/Content/jquery-1/js/jquery.jqGrid.min.js" type="text/javascript"></script>

</head>
<body>
<table id="list"></table> 
<div id="pager"></div> 

</body>
</html>

<script type="text/javascript">


    $(function() {
        alert(33);
        $("#list").jqGrid({
            url: $("#AbsolutePath").val() + "/User.mvc/Index2",
            datatype: 'json',
            ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
            mtype: 'GET',
            colNames: ['UserId', 'Surname', 'Forename', 'Pax', 'Mobile', 'Active', 'Email'],
            colModel: [
        { name: 'UserId', index: 'UserId', width: 80, editable: true, editoptions: { size: 10} },
        { name: 'Surname', index: 'Surname', width: 90, editable: true, editoptions: { size: 25} },
        { name: 'Forename', index: 'Forename', width: 60, align: "right", editable: true, editoptions: { size: 10} },
        { name: 'Pax', index: 'Pax', width: 60, align: "right", editable: true, editoptions: { size: 10} },
        { name: 'Mobile', index: 'Mobile', width: 60, align: "right", editable: true, editoptions: { size: 10} },
        { name: 'Active', index: 'Active', width: 55, align: 'center', editable: true, edittype: "checkbox", editoptions: { value: "Yes:No"} },
        { name: 'Email', index: 'Email', width: 100, sortable: false, editable: true, edittype: "textarea", editoptions: { rows: "2", cols: "20"} }
    ],
            pager: '#pager',
            rowNum: 10,
            rowList: [10, 20, 30],
            sortname: 'Surname',
            sortorder: 'desc',
            viewrecords: true,
            caption: 'My first grid'
        });
    });

</script>
John
  • 1,459
  • 4
  • 21
  • 45
  • I'm not 100% on this but if you change your content-type to application/json it might fix the issue. Here is an example of how its done. http://stackoverflow.com/questions/2675625/setting-the-content-type-of-requests-performed-by-jquery-jqgrid –  Apr 13 '11 at 02:24
  • Your ASPX file: what is it's name? – cwharris Apr 13 '11 at 03:30

4 Answers4

1

I don't know specifically about ASP.NET, but the browser asks if you want to save the file because the file is served with a HTTP Content-Disposition header like this:

Content-Disposition: attachment; filename="..."

rather than Content-Disposition: inline;.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • I've made these changes and still get the same behaviour. I tried setting "ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }," line and also tried "ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }," I then tried both together – John Apr 13 '11 at 02:42
0

I notice that

<%=Html.Action("~/Views/User.mvc/Index2")%>

should in fact be

<%=Url.Action("~/Views/User.mvc/Index2")%>

Html.Action(...) renders the action inline, whereas Html.Url(...) returns the url of the action.

This is probably changing the header information of the Html page, as json results produce different headers than view results, which makes the browser want to download the file rather than render it.

Hope this helps :) text/html

edit:

If you are asking why the Index2 page wants you to download the json file, it's because of the header information. I may have misunderstood the question to begin with. Try the folling:

return Json(results, "text/html")

This will force the content type from "application/octet-stream" to "text/html", and will tell the browser to render the result, rather than try to download it.

edit, again:

Now I'm understanding the real question.

The reason you're not getting the HTML you're expecting is because you're returning a Json result. A Json result tells the controller to serialize an object to json and print it to the response. It does NOT return a view, under any circumstances.

To render a view, you must return an object derived from ViewResultBase. The default Controller class has many View(...) methods that can handle this for you.

You will need two actions in your scenario, the first action will render the view:

public ActionResult Index()
{
    // This will find a view with the name of the action (in this case, "Index")
    return View();
}

Inside your Index.aspx page, you will need to setup jqgrid with

url:'<%= Url.Action("IndexDataJson") %>',

And you'll need another action on your controller to return the jqgrid rows:

public ActionResult IndexDataJson(string sidx, string sord, int page, int rows)
{
    var results = from user in _db.aspnet_Users
                  select new
                  {
                      // Your properties here
                  };

    var usersOnPage = results.Skip((page-1) * rows).Take(rows).ToList();

    // This is the correct format for the jqgrid result
    var model = new
    {
        total = results.Count,
        page = page,
        records = usersOnPage.Count,
        rows = usersOnPage
    }

    // Ignore the "text/html" mentioned earlier, as you probably wont need it
    return Json(model, JsonRequestBehavior.AllowGet);
}

Keep in mind that you may need to modify the ajaxReader for the jqgrid if it doesn't load any data...

Hopefully this fully answers your question. :)

For more information, pleas refer to Phil Haack's blog post about this topic:

http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx

cwharris
  • 17,835
  • 4
  • 44
  • 64
  • Thanks I changed this but i'm still getting the JSON data served as a file. Here is my controller code : – John Apr 13 '11 at 02:39
  • Also, the code you are showing me is your action code, not the controller. The controller is the class which houses all of the actions. – cwharris Apr 13 '11 at 02:50
  • xixonia, this action code is all that the index2.aspx page fires, the rest of the controller code is irrelevant is it not? I can paste into the post if i'm off the mark here – John Apr 13 '11 at 02:58
  • The controller action code runs to the end and contains the expected data. However the JSON code where i place alert or debugger does not run – John Apr 13 '11 at 02:59
  • notice the alert(33); entry, this does not fire, good clue, any ideas? – John Apr 13 '11 at 03:02
  • In your case, the controller code is most likely harmless, however, Json(...) is a method on the controller class. If you were using a subclass of the MVC provided Controller class, the default implementation of the Json method could have been overriden, and could be providing different results than expected. However, I assume your controller inherits directly from the Controller class, so you should have nothing to worry about. That being said, did my edited answer work for you? – cwharris Apr 13 '11 at 03:02
  • Sorry it still gives me a SAVE/OPEN dialogue, going bananas, cannot see whats wrong here, must be something daft. I've updated post with full controller code – John Apr 13 '11 at 03:08
  • $(document).ready(function() { alert(53); $(function() { alert(33); – John Apr 13 '11 at 03:11
  • I honestly can't say for sure what's happening here. by default, the Json(...) method doesn't allow you to perform Get requests. There is a special overload for that. However, your grid is performing a Get request... Are you even getting to the Index2.aspx page? Second, you have two Index2 actions with the same declaration... how are you even compiling that controller? I would start by getting rid of the extra Index2 action, and changing the mtype on the jqgrid to "POST". We can go from there. – cwharris Apr 13 '11 at 03:13
  • Sorry xixonia, the data now appears (raw) in the browser – John Apr 13 '11 at 03:14
  • Another thing: The javascript shouldn't have the function inside the function inside the jQuery call. It should just be $(function(){/*Start doing stuff*/}); – cwharris Apr 13 '11 at 03:14
  • rather than the popup i now get the delimited data in the IE window – John Apr 13 '11 at 03:14
  • Which is what should happen when you navigate directly to the Index2 action... These comments are going on far too long. If you have any additional questions, please update your main post, and see that it is properly formatted before submitting. – cwharris Apr 13 '11 at 03:18
0

It looks to me like the server is responding correctly. It's the browser or the plugin that isn't behaving. Times I've seen the browser attempt to download a JSON result as a file is when the request was not sent asynchronously. I know this is an AJAX plugin, but confirm with fiddler or firebug that the request is sent with an XHR header. You can also check the response header to see what the Content-Type is. I'd start there, examine the request and response for any abnormalities because your code looks right.

On the action side I've never had to include "text/Html in my return Json() calls. I always use this...

return Json(new {message = "some message goes here"} , JsonRequestBehavior.AllowGet);

The response header from this code looks like this..

HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 13 Apr 2011 04:21:47 GMT
Content-Length: 29
BZink
  • 7,687
  • 10
  • 37
  • 55
0

After a second look... How is index2.aspx getting rendered? You never return that View.

That View needs to have been rendered with return View("index2") The jqGrid plugin will then make an additional AJAX call to retrieve the Json data. From the looks of it, you're never actually loading that javascript.

Here's what I would suggest.

public ActionResult Index2()
{
     return View('Index2');
}


public JsonResult Index2Data() //RENAME TO SOMETHING BETTER
        {


            var results = from user in _db.aspnet_Users
                          select new
                          {
                              UserId = user.UserId,
                              Surname = user.Surname,
                              Forename = user.Forename,
                              Pax = user.Pax,
                              Mobile = user.Mobile,
                              Email = user.Email,
                              Active = user.Active,
                              UserName = user.UserName
                          };

            return Json(results, JsonRequestBehavior.AllowGet);

        }

Then in your browser if you hit http://site/User/Index2 you'll first return the aspx page that will load the javascript. As the javascript loads the jqGrid plugin should fire off another call to retrieve the Json data.

Be sure to update your jqGrid url with "index2data" or whatever you call it. The grid needs to know where to get the data from.

BZink
  • 7,687
  • 10
  • 37
  • 55
  • Ita saying JsonRequestBehavior.AllowGet does not exist in current context. Do you know the using clause, many thanks, – John Apr 13 '11 at 08:52
  • I got past this, had to instal MVC 2, but now blank page, still no grid, yikes this is agony – John Apr 13 '11 at 12:06
  • Your jqGrid function is pointing to "/User.mvc/Index2" Do you have a route defined for that? /User/Index2 should work with the default routes defined. Is your alert("33") function firing? – BZink Apr 13 '11 at 22:42
  • Any errors in Firebug in Fiddler? If you're not using both of those tools to debug this, you should be. – BZink Apr 13 '11 at 22:45