Calling Generic MVC Web API from JQuery

So now you have created a Web API with MVC like here and you want to call its functions from JQuery.  Here is how you do it.  
So In this code example, I will be showing you how to create a JQuery function that can call my resource API from the article linked above.  Here are 3 example functions.

function addResource(id) {
        jPrompt('Please enter the Resource Name:', 'Enter Name', 'Prompt Dialog', function (r) {
            if (r) {
                $.ajax({
                    type: "POST",
                    url: "@Url.Action("Resource","api")",
                    data: { ReportsTo: id, Name: r, PercentFullTime: 100, Type: 0 },
                    dataType: "json",
                    success: function (response) { location.reload(); },
                    error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); }
                });
            }
        });
    }
    function deleteResource(id) {
        jConfirm('Are you sure you want to delete this resource?', 'Confirmation Dialog', function (r) {
            if (r) {
                $.ajax({
                    type: "Delete",
                    url: "@Url.Action("Resource","api")" +  '/' + id,
                    success: function (response) { location.reload(); },
                    error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); }
                });
            }
        });
    }
    function getResource(id){
        $.getJSON(
                "@Url.Action("Resource","api")",
                {id: id},
                function (myData) {
                    $('#ClickedId').empty().append(myData.Id);
                    $('#ClickedName').empty().append(myData.Name);
                    $('#ClickedPercent').empty().append(myData.PercentFullTime);
                    $('#ClickedType').empty().append(myData.Type);
                    $('#ClickedReportsTo').empty().append(myData.ReportsTo);
            });
    }
So the first function calls the Post API call. It submits a new resource to be saved. All it does is prompt the user for the name of the resource, and then constructs an ajax call of type POST to the API's URL which I generate with the URL.Action function giving it the controller name and api as a shortcut to construct the URL correctly. After that I just construct the Resource object by giving it the attributes and values that need to be filled in. The Success function reloads the screen so you can see the update. I realize why not just have the server side do the work if I'm posting back, this is just an example, put your display changing logic here. The next function does the same thing with delete. It prompts and then constructs the ajax call. The type is now delete and I couldn't get the data element to construct the id correctly so I concatenated the id to the string, boo. If anyone knows why this doesn't work, I would love to know. Finally, the last function gets the resource with an id. I use the getJSON function because it hides a lot of the ugly of the ajax call. In this one, I give it the base URL again, but am able to use the data to pass id unlike the delete. I then parse the response by just using it as my object, boy that feels nice. There you have it, a WEB API you can expose, and then call in the JQuery right there in your app, no need to duplicate controller methods!

Creating Web API with MVC

Today I revised my Resource project and instead of having custom controllers to call, I tried to consolidate my functions to a Web API.  To do this, I added a new controller to my MVC project with a basic Web API type by right clicking the controllers folder, and selecting Add > Controller.  In the Add Controller dialog, I Named it my object type Controller (ResourceController) and chose "API controller with empty read/write actions" from the Template drop-down.  

This created the basic set of web API functions.  I then made the functions less generic and gave them actual types to return.  Here is the class as I have it implemented, my Resource object now has a web API!

public class ResourceController : ApiController
    {
        // GET api/resource
        public IEnumerable<ResourceModel> Get()
        {
            return DataBridge.GetAllResources();
        }

        // GET api/resource/5
        public ResourceModel Get(int id)
        {
            return DataBridge.GetResource(id);
        }

        // POST api/resource
        public void Post(ResourceModel model)
        {
            DataBridge.AddResource(model);
        }

        // PUT api/resource/5
        public void Put(int id, ResourceModel model)
        {
            model.Id = id;
            DataBridge.SaveResource(model);
        }

        // DELETE api/resource/5
        public void Delete(int id)
        {
            DataBridge.DeleteResource(id);
        }
    }

Creating Right Click Context Menu with JQuery in MFC

So on a tree view I created in an earlier post, I wanted to add the ability to right click an item and have a context menu with a few options for that item.  To do this, I had to learn some new jQuery that I will share here.  My tree had a list of people, the function I will display is how to delete one of the persons clicked through a context menu.  

The first thing to do is add the following js and css files to make this work.  They are the context menu, which relies on position, as well as the alert js which gives us some good prompt dialog.
@Scripts.Render("~/Scripts/jquery.ui.position.js")
        @Scripts.Render("~/Scripts/jquery.contextmenu.js")
        @Styles.Render("~/Scripts/jquery.contextmenu.css")
        @Scripts.Render("~/Scripts/jquery.alerts.js")
        @Styles.Render("~/Scripts/jquery.alerts.css")
Now that we have our libraries in place, we can begin creating the functions.  So I wrapped each item in my list in a div tag.  That div tag has an attribute of ref on it which I store my id in and it has the text inside of it and a class of type context-menu-one (in case we need multiple)
<div class="context-menu-one box menu-1" ref="3">
        <strong>Heath Isely</strong>
    </div>
So to create my context menu, I use the following jquery function.  It calls the contextMenu on my context-menu-one div tags when right clicked with two items, Add Sub and Delete. 
$(function () {
        $.contextMenu({
            selector: '.context-menu-one',
            callback: function (key, options) {
                //var m = "clicked: " + key + ' id:' + $(this).attr('ref');
                //alert(m);
                if (key == "Delete")
                    deleteResource($(this).attr('ref'));
                else if (key == "Add Sub")
                    addResource($(this).attr('ref'));
            },
            items: {
                "Add Sub": { name: "AddChild" },
                "Delete": { name: "Delete" }
            }
        });
});
So now we have a context menu popping up. If you examined it closely, you can also see the callback function is set and detects which item was selected using a simple if block. Inside there, I call other functions depending on the item selected and pass them the id of the item stored in the ref attribute on the div tag we discussed before. The delete function is included below. It simply prompts if you're sure you want to delete the resource. If they click yes, it goes ahead and uses the ajax method to post to my deleteResource function . If it succeeds, it reloads the page to show the updated list.
function deleteResource(id) {
        jConfirm('Are you sure you want to delete this resource?', 'Confirmation Dialog', function (r) {
            if (r) {
                $.ajax({
                    type: "POST",
                    url: "@Url.Action("deleteResource","Home")",
            data: { ListID: id },
            dataType: "json",
            success: function (response) { location.reload(); },
            error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); }
                 });
            }
        });       
    }
The final piece I will show is the function on the server side for the delete call. It does the delete to the database and then responds with a json success response.
[HttpPost]
        public ActionResult deleteResource(int ListID)
        {
            DataBridge.DeleteResource(ListID);
            return Json("result", "success");
        }

Creating HTML Treeview on website wth MVC and JQuery

There are many ways to create a tree view on the web, today I wanted to talk about a simple way.  What I did was declare an object called resource, in this case people, that report to one another.  So its an object that links to other objects of its own type.  Here is the resource class as I am using it. The DataBridge is just my data access class in this case.
public class ResourceModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ReportsTo { get; set; }
        public EResourceType Type { get; set; }
        public int PercentFullTime { get; set; }
        public IList<ResourceModel> GetChildren
        {
            get
            {
                if(_children == null)
                    _children = DataBridge.GetModels(Id);
                return _children;
            }
        }
        private IList<ResourceModel> _children = null;
    }
Next, I created a web page that renders a list of ResourceModels.  The list I respond to this page is the root level resources.  This is what that super simple page looks like.
@model IEnumerable<ResourceManager.Models.ResourceModel>

@{
    ViewBag.Title = "ResourceEdit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Resources Edit</h2>

<ol id="treeview">
@Html.DisplayForModel(Model)
</ol>
<script type="text/javascript">
    $().ready(function () {
        //default, basic treeview
        $("#treeview").bonsai({expandAll:true});
    });
</script>
I should note that I am using the JQuery library called Bonsai to convert my ol li list to a tree view before I go any further.  There are a number of JQuery libraries that do the same thing, this is just the first that Google Returned that looked reasonable.  I had to modify the header to include links its css and js file as well as make sure JQuery was being included.
@Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/Scripts/jquery.bonsai.js")
        @Styles.Render("~/Scripts/jquery.bonsai.css")
That's almost it, as you could see, I was using the Html.DisplayForModel(Model) in the treeview which renders a list of ResourceModels.  For this, I implemented a partial view for the ResourceModel type and put it in the Shared/DisplayTemplates folder.  Here is the content of that recursive view.  
@model ResourceManager.Models.ResourceModel
<li>@Model.Name
    @if(Model.GetChildren.Count() > 0){
    <ol>
        @Html.DisplayFor(model=>model.GetChildren)
    </ol>
    }
</li>
It utilizes the GetChildren property I exposed on the class to get all child elements as it re curses the tree.  Its rather slick actually.  Because it had to do a count check before actual list, I cached the results on the object as you could see in the class storing the children as a private variable.

MVC 4 Install on IIS 7 First time 404.14 Error

Ok, I have run into this a few times installing MVC for the first time on IIS.  You copy the file out to the server, set up the application and nothing happens.  Here are the steps I go through to solve the problem.

1. Make sure .Net is installed to the version of your site.  In the MVC case make sure you have 4.0 or better most likely and compile your site to that version by right clicking your Project Properties and setting the .Net version.  If you need a later version, install it on the server.

2. After IIS is installed, register that version of IIS there.
cd \
cd Windows\Microsoft.NET\Framework\v4.xxx.xxx
aspnet_regiis -i

3. If it still doesn't work you may have to look in your config file.  One line I had to add to get things working was the following.
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    ...
<system.webServer>
4. If your still getting the 403, you need to start looking at the permissions used.  If the site is using windows authentication, do you have rights to use it on that server?  Perhaps you need to use impersonate like below.
<system.web>
    <identity impersonate="true" userName="domain\username" password="password"/>
</system.Web>
Another common line of code that will cause issues is the deny users, remove this from the config if need be, but make sure to take care of that authentication then.  
<authorization>
      <deny users="?"/>
</authorization>
Good Luck!