Solved

MVC4 Web API Service &  MVC4 AngularJS Get?

Posted on 2014-04-08
14
715 Views
Last Modified: 2014-04-16
Just now breaking into AngularJS and MVC4. I have a working test service on our local 2012 server which returns xml in a dev browser like so:
192.168.1.11:8080/api/values

<ArrayOfPerson>
   <Person>
      <ID>1</ID>
      <Name>sankar</Name>
      <Address>cuttack</Address>
      <DOB>1983-01-22T00:00:00</DOB>      
   </Person>
   <Person>
      <ID>3</ID>
      <Name>My Test Name</Name>
      <Address>My Test Address</Address>
      <DOB>1980-01-01T00:00:00</DOB>     
   </Person>
</ArrayOfPerson>

Open in new window

I have a dev running VS2012 and MVC4 project with the following code. I'm trying to return a list of Persons. Instead it never errors or returns any data.

Q. What am I doing incorrectly?

public class ValuesController : ApiController
    {
        PersonEntities db = new PersonEntities();
        
        public IEnumerable<Person> Get()
        {
            return db.Persons.ToList();
        }
}

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div ng-controller="GetPeople">
    <table>
        <tr ng-repeat="person in persons">
            <td>{{person.Id}}</td>
        </tr>
    </table>    
</div>

<script src="~/Scripts/angular.min.js"></script>
<script type="text/javascript">

    function GetPeople($scope, $http) 
    {
        $http.get('192.168.1.11:8080/api/values').
            success(function (data) 
            {
                $scope.values = data;
            });
    }
</script>

Open in new window

0
Comment
Question by:WorknHardr
  • 7
  • 6
14 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
How do you know it's not erroring? I don't see where you have attached a handler to the error callback. Have you tried running a utility like Fiddler to see data going over the wire?
0
 
LVL 5

Expert Comment

by:jayakrishnabh
Comment Utility
Is the webservice a ScriptService and the method a ScriptMethod for it to be accessed from javascript.
Also, as kaufmed suggested, please try using error handler to check whether if it is errored while calling the script method.
0
 

Author Comment

by:WorknHardr
Comment Utility
So far I run debug in Firefox / IE using F12 and no error. AngularJS is new to me and so is debugging it.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
...and no error.
OK, but again have you attached to the error callback? There is a difference between a Javascript error and an error (code) being returned from a web service. The former causes your script to stop working, and it's what shows up in a debugger; the latter is normal operation, and it won't stop your script from running.
0
 

Author Comment

by:WorknHardr
Comment Utility
I'm also concerned that the Web Api service returns XML and I don't know if AngularJS expects JSON or XML?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
I'm also concerned that the Web Api service returns XML...
Well, lucky for you Web API returns either XML or JSON right out of the box. (This assumes that you are not returning string from your service call, and passing XML that you yourself serialized.) Read up on content negotiation.

If you are serializing the XML yourself, then content negotiation is out the window. Still, I don't see why Angular won't accept XML. Data is data.
0
 

Author Comment

by:WorknHardr
Comment Utility
The Web API service is now returning JSON instead of XML like so by simply typing this url in a browser window: 192.168.1.11:8080/api/values
[{"ID":1,"Name":"sankar","Address":"cuttack","DOB":"1983-01-22T00:00:00"},{"ID":3,"Name":"My Test Name","Address":"My Test Address","DOB":"1980-01-01T00:00:00"}]

Open in new window

Note: I also downloaded 'Fiddler' and the data string above returns in it as well.

As a JSON test I'm using the AJAX code below, it too never returns any data and the error alert never opens.
Note: I've never had this much trouble returning data to a web page using MVC Action Results and Views. It seems like returning JSON would be much easier than this. As you said before, "it's just data", I say it's like pulling teeth...
<div>
    <table id="tbPerson"></table>
</div>

<script src="~/Scripts/jquery-2.1.0.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () 
{
$.ajax({
            url: '192.168.1.11:8080/api/values',
            type: 'GET',
            dataType: "json",
            contentType: 'application/json; charset=utf-8',
            success: function (data)
            {
                for (var i = 0; i < data.length; i++)
                {
                    $("<tr> <td>" + data[i].Name + "</td> </tr>").appendTo("#tbPerson");                   
                }
            },
            error: function (xhr, status, error)
            {              
                    alert(error);
            }
        });
});
</script>

Open in new window

0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
I haven't yet played with Angular, but I'm always up for a challenge. I'll take a look at it tonight when I get home from work, and I'll see if I can work up an example for you.
0
 

Author Comment

by:WorknHardr
Comment Utility
Any success?
0
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
Sorry, I looked at it, but I started running into cross-origin errors, so I had to work that out.

Keep in mind that I've only started looking at Angular, but what mainly jumps out at me is that you don't have the ng-app directive anywhere. For example:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/angular")
</head>
<body ng-app>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>

Open in new window


Notice how I've added it to the <body> tag. So now when all of my HTML is rendered:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="/Content/site.css" rel="stylesheet"/>
    <script src="/Scripts/modernizr-2.6.2.js"></script>
    <script src="/Scripts/angular.js"></script>
</head>
<body ng-app>
<h2>Index</h2>
<div ng-controller="GetPeople">
    <table>
        <tr ng-repeat="person in values">
            <td>{{person.Id}}</td>
        </tr>
    </table>    
</div>
<script type="text/javascript">
    function GetPeople($scope, $http) {
        $http.get('http://localhost:60455/api/values').
            success(function (data) {
                $scope.values = data;
            });
    }
</script>
    <script src="/Scripts/jquery-1.8.2.js"></script>    
</body>
</html>

Open in new window


The other issue I see is that you called the property values when you assigned it to the $scope, but you referred to it as people in your ng-repeat. Pick one or the other. (I went with values above.)

using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace MvcApplication1.Controllers
{
    public class ValuesController : ApiController
    {
        PersonEntities db = new PersonEntities();

        public IEnumerable<Person> Get()
        {
            return db.Persons.ToList();
        }
    }

    public class PersonEntities
    {
        public PersonEntities()
        {
            this.Persons = new List<Person>()
            {
                new Person() { Id = 1 },
                new Person() { Id = 2 },
                new Person() { Id = 3 },
            };
        }

        public IEnumerable<Person> Persons { get; set; }
    }

    public class Person
    {
        public int Id { get; set; }
    }
}

Open in new window


Screenshot
0
 

Author Comment

by:WorknHardr
Comment Utility
Excellent! It's working! Yea!

Q. To be clear,  the $scope.values must match the controller name 'Values'

It's been a mystery to me where other Internet examples get the scope sub-name...
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
Q. To be clear,  the $scope.values must match the controller name 'Values'
No. It must match what you have in your ng-repeat. Think of ng-repeat as a C# foreach loop, where you have the form:

foreach (var variable in collection)

Open in new window


In $scope.XXXX, "XXXX" must be collection.

i.e.

$scope.collection

Open in new window


For the moment, ignore my code and focus on your original code. the $scope line would need to be:

$scope.people = data;

Open in new window

0
 

Author Comment

by:WorknHardr
Comment Utility
Yea, I see that now. I kept thinking it must be hard-typed somewhere else to show in intellisense.

Thanks, you are good teacher...
0
 

Author Closing Comment

by:WorknHardr
Comment Utility
Thx again...
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Requirements JQuery 1.6+ HTML CSS Introduction This article was inspired by an EE question (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_28372511.html) on how to make a page show some balloons animate up a page…
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now