Web API Call is not working - asp.net-mvc-4

This is the first time I am using the Web API component in MVC 4. I just created a Web API project to manage a person details. I wrote a get function in Person Controller and called it from browser. The result is:
<ArrayOfPerson xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPITest.Models">
<Person>
<Address>Addr</Address>
<DOB>2013-05-04T00:00:00</DOB>
<ID>1</ID>
<Name>Name</Name>
</Person>
</ArrayOfPerson>
The URL is: http://localhost:3802/api/Person
Then I added a new MVC basic project to the solution and tried to call the Web API from the view page.
The code in view page is :
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script>
$(document).ready(function () {
$.ajax({
url: "http://localhost:3802/api/Person",
type: "Get",
success: function (data) {
for (var i = 0; i < data.length; i++) {
$("<tr></tr><td></td>" + data[i].Name + "</td><td></td>" + data[i].Address + "</td><td></td>" + data[i].DOB + "</td></tr>").appendTo("#tbPerson");
}
},
error: function (msg) { alert("Error"); }
});
});
</script>
<h2>Index</h2>
<table id="tbPerson">
<tr>
<th>Name</th>
<th>Address</th>
<th>DOB</th>
</tr>
</table>
But I am getting the alert box showing the Error. Can anyone help me out?

Since you added a new MVC project, it will run in a port other than 3802. So, the page URI will be something like http://localhost:<someport>/home/index. If JavaScript from this page calls the URI of your API endpoint, which is http://localhost:3802/api/Person, the request becomes a cross-origin request and browser does not allow it. For more info, take a look at http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api. There is a great MSDN article by Brock Allen on this topic - http://msdn.microsoft.com/en-us/magazine/dn532203.aspx.

Try to change url: "http://localhost:3802/api/Person"
to
url: "/api/Person"

Related

Cannot get JSON response from API

I have a RESTful API web service. I'm programming a simple pure Javascript client app to interact with the APIs. I also use Knockout framework. My Javscript code:
self.movies = ko.observableArray();
$.get(self.moviessURI, function(data){
var obj = JSON.parse(data);
for (var i=0; i < obj.movies.length; i++) {
self.movies.push(obj.movies[i]);
}
}, "json");
My HTML code:
<table class="table table-striped">
<tr><td><b>Title</b></td><td><b>VideoID</b></td></tr>
<!-- ko foreach: movies -->
<tr>
<td><p><b data-bind="text: title"></b></p></td><td><p data-bind="text: videoId"></p></td>
</tr>
<!-- /ko -->
</table>
After running, I have a request status 200 on the web service, but my client app does not display anything. I also used Postman to test the API and its working.
Where did I do wrong? Thanks for any help!

Google-plus sign in: the code runs twice, user was logged out right after he logs in

this is a page built on example
<html>
<head>
<title>Demo: Getting an email address using the Google+ Sign-in button</title>
<style type="text/css">
html, body { margin: 0; padding: 0; }
.hide { display: none;}
.show { display: block;}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<!--<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>-->
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
<script type="text/javascript">
/*
* Triggered when the user accepts the sign in, cancels, or closes the
* authorization dialog.
*/
function loginFinishedCallback(authResult) {
if (authResult) {
console.log('authResult : ',authResult);
if (authResult['error'] == undefined){
gapi.auth.setToken(authResult); // Store the returned token.
toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
getEmail(); // Trigger request to get the email address.
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
/*
* Initiates the request to the userinfo endpoint to get the user's email
* address. This function relies on the gapi.auth.setToken containing a valid
* OAuth access token.
*
* When the request completes, the getEmailCallback is triggered and passed
* the result of the request.
*/
function getEmail(){
// Load the oauth2 libraries to enable the userinfo methods.
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(getEmailCallback);
});
}
function getEmailCallback(obj){
var el = document.getElementById('email');
var email = '';
console.log("OBJ = ",obj)
if (obj['email']) {
email = 'Email: ' + obj['email'];
}
//console.log(obj); // Uncomment to inspect the full object.
el.innerHTML = email;
toggleElement('email');
}
function toggleElement(id) {
var el = document.getElementById(id);
if (el.getAttribute('class') == 'hide') {
el.setAttribute('class', 'show');
} else {
el.setAttribute('class', 'hide');
}
}
</script>
</head>
<body>
<div id="signin-button" class="show">
<div class="g-signin" data-callback="loginFinishedCallback"
data-approvalprompt="auto"
data-clientId="751931329576.apps.googleusercontent.com"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="http://semicon-equip.com"
>
</div>
<!-- In most cases, you don't want to use approvalprompt=force. Specified
here to facilitate the demo.-->
</div>
<div id="email" class="hide"></div>
</body>
</html>
Question 1: It always fails with "Uncaught TypeError: Cannot read property 'load' of undefined",
until I use
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
instead of the example code:
<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>
What's the difference between plusone.js and client:plusone.js ?
Question 2: Why the code run twice per page loads ?
Qestion 3: the user was logged out after he just signed in, how to fix ?
error demo page for the above (all the errors are in the background console).
This is not really an answer to the question, but a step by step procedure to reproduce it.
Below the simple html page I'm using to test (similar to the example from Ray C Lin).
I've made it as simple as possible to avoid interactions with other part of the code :
<html>
<head>
<script type="text/javascript"
src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<input type="button" id="signOut" value="Sign out"></button>
<span id="signinButton">
<span class="g-signin"
data-accesstype="offline"
data-callback="signinCallback"
data-clientid="YOUR_CLIENT_ID_HERE"
data-cookiepolicy="single_host_origin"
data-scope="email"
</span>
</span>
<script type="text/javascript">
$('#signOut').on('click', function() {
gapi.auth.signOut();
});
function signinCallback(authResult) {
console.log("signinCallback: ", authResult);
}
(function() {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</body>
</html>
You will have to update data-clientid with your own google client id, and display this page from an authorized javascript origin.
Please note that this might not work from localhost, as Ian suggested in a comment to this post https://plus.google.com/102746521318753162868/posts/Z5Gkro9YXVs
First, sign in using your Google account : you will see a successful callback in the console.
If you click on Sign out, you will see a callback with 'user_signed_out' in the console.
So far so good.
Sign-in again, and wait 1 hour, until the token expires (this is awful to test, as I don't know how to reduced the token lifetime).
After one hour, click on the sign out button : no callback is called.
Click on the sign-in button again :
you get a successfull callback with an authorization code and access token
immediately after, you get a 'user_signed_out' callback.
Once a session has expired, there is no way to return to a "normal" situation, you always get this second callback with 'user_signed_out'.
Actually, there is one way to return to a "normal" situation: revoke the access to the app from the google dashboard.
This is not really an issue for me as I'm using Google+ only to sign-in the user to my app using the one time authorization code, and I'm not using the access token from the client.
But this prevent automatic login from working, as the user is immediately considered as "signed out" from a google perspective.
Q1: client:plusone.js is just telling the loader to automatically load the "client" module. It's basically automatically doing gapi.load("client"), except it is already packaged up for you in one download. You could do it the other way around as well, plusone:client.js!
Q2: Not sure, it may be some JS quirk. In general, try and make your code able to handle multiple callbacks, you may get another if the state changes (e.g. the user logs out of their google account).
Q3: I don't see that on the test page - I am signed OK, and still signed in on refresh! Check you're not blocking third party cookies in your browser or similar?

xmlhttp request cannot load-origin null is not allowed by access control-Allow origin

i am beginner to Phonegap, here i am executing this reference code in Android Emulator and working in phonegap 2.0 to get simple output. After running this code, Logcat shows the following error:
xmlHTTPrequest cannot load http://api.careerbuilder.com/v1/jobsearch?DeveloperKey? origin null is not allowed by access control-Allow origin
here html code:
<div data-role="page" id="page1">
<div data-role="header" data-theme="b">
<p><center>Career Builder</center></p>
</div>
<div data-role="content" data-theme="d">
<input type="text" id="t1" placeholder="Location....">
<input type="button" id="but" value="Search" onclick=show()><br>
<ul id="list" data-role="listview" data-theme="a" data-filter="true">
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
}
function show() {
var val=document.getElementById("t1").value;
$.ajax({
type: "GET",
url: "http://api.careerbuilder.com/v1/jobsearch?&DeveloperKey= my api key",
contentType:"xml/application",
data:{
val:val,
},
dataType: "xml",
success: function(xml)
{
xmlParser(xml);
}
});
}
function xmlParser(xml) {
$(xml).find("JobSearchResult").each(function () {
var com=$(this).find("Company").text();
var job=$(this).find("JobTitle").text();
$("#list").append
('<ul><li>Company Name :' + com + '</li><li>Job Title :' + job + '</li><ul>');
$('#list').listview('refresh');
});
}
This is caused by the same-origin policies enforced by all modern browsers. Read up on how CORS works for more details. Basically the issue is that your web page is on a different domain than the careerbuilders.com URL, and the CORS headers are either not transmitted correctly by careerbuilders.com, or aren't interpreted correctly by phonegap.

Multi language support in Hot towel(Durandal framework)

I'm in the process of creating a application using Hot Towel, which supports multiple language (eg. english, french)
I have the referred the following links
Translating Views
Durandal localization example
And my question is how can i render views of application based on user language. If user selects english, the complete application should display contents in english. How to achieve this
I have tried something like in the second link.
define({
'root': {
welcome: 'Welcome!',
flickr: 'Flickr'
},
'fr-fr': true,
'es-es': true,
});
Is this i have to create seperate views for languages or i have to create seperate App folder for contents
Suggest me some best practices.
I don't recommend using separate views or separate folders if your project is a big one.
You can just create a file of the labels and if you use lib like knockout just data-bind these labels once (text: xxxx). In addition you can use i18n to manage labels.
With selected language just load the specific language file to your viewmodel.
EDIT1:
I'd never encountered a complete sample nor tutorial. So how I do is to :
use tools like i18n to get the key-paired dictionary file for labels in html and in some javascript code like messages.
then manually I indexed these labels by augmenting knockout viewmodels for views and variables for modules.
This is my last option in waiting for better solution. Hope this can help!
you can do some thing like this . YOu can change the APP folder if you are need do lot of locale changes you can use the following method
#{
string strAcceptLanguage;
strAcceptLanguage = System.Configuration.ConfigurationManager.AppSettings["Locale"].ToString();
if (strAcceptLanguage == "en-us")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-US/main"></script>
}
else if (strAcceptLanguage == "es-es")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-UK/main"></script>
}
else if (strAcceptLanguage == "fr-fr")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="AUZ/main"></script>
}
}
in the Index.cshtml you can use the above code and for the you need to have value in Webconfig file
<add key="Locale" value="en-us" />
and in the SPA page each time when the user try to change the locale by pressing button or any kind of option you have to trigger a event to call a AJAX post to assess a REST api to update the Given Locale Value in the webconfig file
changeLocale: function (val) {
var name = JSON.stringify({
locale: val
});
$.ajax({
cache: false,
url: "http://localhost:49589/api/Locale",
type: "POST",
dataType: "json",
data: name,
contentType: "application/json; charset=utf-8",
processData: false,
success: function (json) {
alert(json);
location.reload();
},
error: function (json) {
alert("error" + JSON.stringify(json));
}
});
you have to write the above code in the shell.js and the shell.html has the following code
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'en-us')">English</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'es-es')">French</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'fr-fr')">Japanese</button>
</div>
And the rest api like this
[HttpPost]
public string ChangeLocale(Locale l)
{
ConfigurationManager.AppSettings["Locale"] = l.locale;
return "success";
}
hope this will help

IE 11 (or 10) kendo ui file upload will not upload unless I refresh the page (ctrl-F5)

Environment specifics:
MVC4 app
Kendo UI File Upload
IE 11 (or 10)
Windows Authentication
When I load the view for the application that has the file upload kendo tool in IE the file upload returns a 401 unauthorized error (traced from server). If I refresh the page (ctrl-F5) then the tool works fine. This tool works fine with Chrome.
any idea why or how to fix?
you will not believe the insanity I had to go through to get a solution to this:
I dropped a document ready jquery snippit at the end of the document to force it to authenticate an action on my controller.
<div id="checkauth" style="display: none;"></div>
<script type="text/javascript">
$(function () {
$.ajax({
url: '\AcceptanceFileValidator\CheckAuth'
}).done(function (d) {
$('#checkauth').html(d.uid)
});
});
</script>
and on the controller:
public JsonResult CheckAuth()
{
return Json(new { uid = Guid.NewGuid().ToString() }, JsonRequestBehavior.AllowGet);
}