Calling a Web Api 2 Method using Ajax - javascript

I have a Web Api 2 project which I used for a mobile project. I am trying to use the same api's for a web project but am unable to reach them using ajax. I've confirmed that my url is correct and I am able to hit the endpoint from an android project and from fiddler. Am I missing something is my ajax call? I always hit the error function, which returns 'undefined'. I can set a breakpoint in my webapi project and that endpoint is never being hit.
// GET: api/Trips
public IQueryable<Trip> GetTrips()
{
return db.Trips.Include("Users");
}
jquery
$.ajax({
url: 'http://localhost:49669/api/Trips',
type: 'GET',
contentType: 'application/json;charset=utf-8',
success: function (data) {
alert("success!!");
},
error: function (x, y) {
alert(x.response);
}
});

You may need to enable CORS if trying to hit your API form a browser.
Step 1, modify your WebApiConfig file (App_Start/WebApiConfig.cs):
using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Add this line
config.EnableCors();
// the rest of your code
}
}
}
Step 2, add the [EnableCors] attribute to your Web API controller:
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace MyApp.Controllers
{
[EnableCors(origins: "http://www.whatever.net", headers: "*", methods: "*")]
public class HelloWorldController : ApiController
{
// GET: api/Trips
public IQueryable<Trip> GetTrips()
{
return db.Trips.Include("Users");
}
}
}
**Note: ** You may also need to install the CORS nuget package.
Install-Package Microsoft.AspNet.WebApi.Cors

contentType is for the content type beint sent to the server; this is the only possible reason I can imagine your code not working since you said it's never actually making the request so it must be some error handling done by jQuery before making the request, and the error is being thrown because you are trying to specify contentType for a GET request.
The property for specifying a response type is dataType. Try changing contentType to dataType?

Related

how to restrict cross origin request for other domains using CORs

I am working on asp.net web api project I want allow only my domain access but its working fine when i calling my webapi from JavaScript but problem is when i calling web api from c# code it allows any domine to access how can i restrict this i want give access only for my domain
I am working on asp.net web api project I want allow only my domain access but its working fine when i calling my webapi from JavaScript but problem is when i calling web api from c# code it allows all domine to access how can i restrict this..? i want give access only for my domain
You can use Microsoft.AspNet.WebApi.Cors, a Nuget package from Microsoft.
Follow these step:
install package for your API project.
add one line code to your App_Start/WebApiConfig.cs file to enable the function: config.EnableCors();
using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
use attribute in your controller or action like this:
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace WebService.Controllers
{
[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
}
You can get more info here
1=> var cors = new EnableCorsAttribute("http://mydomain", "*", "*"); config.EnableCors(cors);
I wrote this code in web config file as global level but its working fine when I am calling my web api from client side its allowing only for specified domain
2=> This is my Client side code
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
$ $.ajax({
url: "http://localhost:49676/Account/ValidLogin",
method: "get",
data: Employee,
dataType: "json",
//contentType: "application/json",
success: function (data) {
GetAllEmployee(data);
alert("success");
console.log(data);
},
error: function (err) {
alert("error");
}
3. I wrote some code I web config file to restrict other domain request but when i calling web api by client side it allowing any domine to access so my problem is I want to restrict my api form Other public domain
Here is my server side code
protected void btnDelete_Click(object sender, EventArgs e)
{
string strUrl = string.Format("http://mydomain/account/validlogin?username=admin&password=admin");
HttpWebRequest requestObjectGet = (HttpWebRequest)HttpWebRequest.Create(strUrl);
requestObjectGet.Method = "GET";
HttpWebResponse responseObjectGet = null;
responseObjectGet = (HttpWebResponse)requestObjectGet.GetResponse();
string strresulttest = null;
using (Stream stream = responseObjectGet.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresulttest = sr.ReadToEnd();
JavaScriptSerializer js = new JavaScriptSerializer();
string StrToken = js.Deserialize<string>(strresulttest);
Session["ApiToken"] = StrToken;
}

Using #Consumes annotation on Rest API call giving 500 Internal Server Error

I am trying to build a custom build plugin using Atlassian sdk framework and in that I have developed a custom build Rest API to update data stored in database.
I am invoking the rest API using AJAX call from JavaScript file as given below:
$.ajax({
headers:{
'Content-Type':'application/json',
'Accept': 'application/json'
},
url : serviceUrl + "rules/update",
type: "POST",
data : ruleObj
})
This API call will invoke the following REST API:
#Path("/rules")
public class fieldsResource {
#POST
#Path("/update")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public Response update(#Context
HttpServletRequest req, #Context
HttpServletResponse res) {
jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext();
appuser = jiraAuthenticationContext.getLoggedInUser();
// Fetch rule id of rule which need to be updated
final int ruleId = Integer.parseInt(req.getParameter("id"));
Rules rule = rule.findRuleById(ruleId);
boolean ifUserHasRequiredAccess = ifUserHasRequiredAccess(req, res, projectKey, appuser,
userManager, jiraAuthenticationContext, loginUriProvider);
if (ifUserHasRequiredAccess) {
log.warn("Update API is invoked for rule " + ruleId + " to update Action triggered by : " + appuser);
return Response.noContent().build();
}
return Response.status(401).build();
}
}
Initially without adding Content-Type, Accept in JS file and without adding #Consumes({ MediaType.APPLICATION_JSON })
The API call was successful, but After adding #Consumes({ MediaType.APPLICATION_JSON }), I am getting 500 Internal Server Error.
I tried adding 'text/plain' also, then also it is throwing 500 Internal Server Error.
I need to add #Consumes({ MediaType.APPLICATION_JSON }) for this API call.
Can anyone please guide me on resolving this issue?
As per your code snippet, you are not returning any object in the response body.
return Response.noContent().build();
or
return Response.status(401).build();
#Consumes expects a json response being returned from your API.
Do you want the API to return any response?

Return JSON from C# and deserialize it back in JS [duplicate]

I created an ASMX file with a code behind file. It's working fine, but it is outputting XML.
However, I need it to output JSON. The ResponseFormat configuration doesn't seem to work. My code-behind is:
[System.Web.Script.Services.ScriptService]
public class _default : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)]
public string[] UserDetails()
{
return new string[] { "abc", "def" };
}
}
To receive a pure JSON string, without it being wrapped into an XML, you have to write the JSON string directly to the HttpResponse and change the WebMethod return type to void.
[System.Web.Script.Services.ScriptService]
public class WebServiceClass : System.Web.Services.WebService {
[WebMethod]
public void WebMethodName()
{
HttpContext.Current.Response.Write("{property: value}");
}
}
From WebService returns XML even when ResponseFormat set to JSON:
Make sure that the request is a POST request, not a GET. Scott Guthrie has a post explaining why.
Though it's written specifically for jQuery, this may also be useful to you:
Using jQuery to Consume ASP.NET JSON Web Services
This is probably old news by now, but the magic seems to be:
[ScriptService] attribute on web service class
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] on method
Content-type: application/json in request
With those pieces in place, a GET request is successful.
For a HTTP POST
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] on method
and on the client side (assuming your webmethod is called MethodName, and it takes a single parameter called searchString):
$.ajax({
url: "MyWebService.asmx/MethodName",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ searchString: q }),
success: function (response) {
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + jqXHR.responseText);
}
});
A quick gotcha that I learned the hard way (basically spending 4 hours on Google), you can use PageMethods in your ASPX file to return JSON (with the [ScriptMethod()] marker) for a static method, however if you decide to move your static methods to an asmx file, it cannot be a static method.
Also, you need to tell the web service Content-Type: application/json in order to get JSON back from the call (I'm using jQuery and the 3 Mistakes To Avoid When Using jQuery article was very enlightening - its from the same website mentioned in another answer here).
Are you calling the web service from client script or on the server side?
You may find sending a content type header to the server will help, e.g.
'application/json; charset=utf-8'
On the client side, I use prototype client side library and there is a contentType parameter when making an Ajax call where you can specify this. I think jQuery has a getJSON method.
Alternative: Use a generic HTTP handler (.ashx) and use your favorite json library to manually serialize and deserialize your JSON.
I've found that complete control over the handling of a request and generating a response beats anything else .NET offers for simple, RESTful web services.

How can I test my web api Post Web method to know what's going on inside?

So here's my situation...
We have an on-prem installation of Microsoft Dynamics CRM and I am trying to make an ajax call from it to a service I created on another one of our servers. There have been many issues already that I've solved - but I'm able at this point to successfully make a GET request to my service from CRM via javascript I've put on a form in CRM.
Just for reference (because I'm not entirely sure at this point if these things are related or not)...
I had to set anonymous authentication in IIS for my service (CRM has
its own authentication that I will be relying on)
I had to set a response header of Access-Control-Allow-Origin with the host address of our CRM installation
So, after doing those things I was able to successfully call my web service via GET. I could return back a string I had from a [HttpGet] web method.
But, now I need to actually call a web method via POST to post some data to my web service. So, below you can see my implementation for the service as well as the javascript I'm using the make the POST call.
using CRMService.Models;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Mail;
using System.Web;
using System.Web.Http;
namespace CRMService.Controllers
{
public class DefaultController : ApiController
{
// GET: Default
public string Get()
{
return "Hi";
}
[HttpPost]
public string GiveParameters(TestClass tc)
{
try
{
Dictionary<string, object> Parameters = new Dictionary<string, object>();
Parameters.Add("id", tc.id);
Parameters.Add("one", tc.one);
Parameters.Add("two", tc.two);
NonQuery("InsertTestItem", ConfigurationManager.ConnectionStrings["TestConnection"].ToString(), Parameters);
return "success";
}
catch (Exception ex)
{
return "ex";
}
}
}
}
var new_budget = Xrm.Page.data.entity.attributes.get("new_budget").getValue();
var new_name = Xrm.Page.data.entity.attributes.get("new_name").getValue();
var id = Xrm.Page.data.entity.getId();
data = '{"TestClass":{"one":"' + new_name + '", "two":"'+ new_budget +'", "id":"'+ id +'"}}'
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "https://<hiddingMyUrl>/api/Default/GiveParameters",
data: data,
dataType: "json",
success: function(data) {
console.log("Success");
},
error: function(result) {
console.log("Error");
}
});
When I make this POST call, at first I could see it was doing some "preflight" stuff and making an OPTIONS request - then returning a 403 (I think, if memory serves me right). I looked that up and solved that issue by adding a Access-Control-Allow-Headers header to my web service in IIS with the value of Origin, X-Requested-With, Content-Type, Accept
After doing that my POST actually gives a 200 status code - but, as you can see in my code, I should then be seeing data in a database if everything went well.
..So of course then the question is... is my web service code working properly? And normally I could test for that easily - however I am fairly new to web api. I don't really get the best way to testing at this point - and I don't know if it's something with my code specifically or if there is some configuration issue with web api itself.
Here is my routeconfig:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
}
You should try working with a REST client.
Here are two nice ones :
Advanced Rest Client
Postman
I personally prefer Postman but really both are good.

Data at the root level is invalid on $.ajax call

I have a simple web service that I am trying to utilize. Obviously, this will be more enahnced down the road but am trying to grasp the basic concept of the ajax call.
Web Service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace Tools
{
/// <summary>
/// Summary description for CFServices1
/// </summary>
[WebService(Namespace = "http://localhost:51342/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class CFServices1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hellow World";
}
}
}
JavaScript
$.ajax({
type: "POST",
url: "CFServices.asmx?/HelloWorld",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
console.log(data);
},
error: function (response) {
console.log(response);
}
});
The ajax call appears to work fine as it returns an error:
"<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Receiver</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlTextReader.Read()
at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.Read()
at System.Xml.XmlReader.MoveToContent()
at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.MoveToContent()
at System.Web.Services.Protocols.SoapServerProtocolHelper.GetRequestElement()
at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest()
at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)
--- End of inner exception stack trace ---</soap:Text></soap:Reason><soap:Detail /></soap:Fault></soap:Body></soap:Envelope>"
I have tried a couple different things that lead me down the path of the URL property being invalid but since I'm getting an actual response, I'm assuming it's correct. It definitely renders if I navigate to it through a browser. Even if I try and invoke the web service through the asmx page, it all works.
I have tried changing the data type to be plain text but that doesn't work either. Since all the web method does is reutnr the string 'Hellow World', I shouldn't need to pass any arguments but tried passing blank values just in case. Everything either brings me back to the response returning 'undefined', the html markup for the asmx page or this. The 'data at the root element is invalid.' This tells me that either the data being sent to, or recieved from the web service is incorrect or doesn't have the right formatting. This is where I'm getting hung up at because I can't figure out what could possibly be wrong here.
Although this is something probably simple, I'm not finding any luck whatsoever on SOF or other threads. Any helpful insight is greatly appreciated.
As we are calling it from jquery ie., from script part you need to make the below changes to Webservice part,
[System.Web.Script.Services.ScriptService] // Mark it for accessing from script
public class CFServices1 : System.Web.Services.WebService
We need to set script method attribute for the web method as below
[WebMethod]
[ScriptMethod]
public string HelloWorld()
Then while calling it from ajax call just remove ? in url part as below,
$.ajax({
type: "POST",
url: "CFServices.asmx/HelloWorld",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
console.log(data);
},
error: function (response) {
console.log(response);
}});
Hope it helps.
I had everything thilsiva suggested but was still receiving this error. It worked on my local development machine but not when deployed. The problem was I was getting my URL from the config file and I was accidentally missing the method name in my deployed version. So make sure you have the method name included if you're in the same situation.
url: "CFServices.asmx/HelloWorld",
not
url: "CFServices.asmx",

Categories

Resources