I need to allow a custom header called "secretToken". And every call to my webapi, the user should pass this header.
I searched for a way to do that, but I could not found an easy way. How can I allow this custom header?
There's one more thing in .config file:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept,auth-key" />
</customHeaders>
</httpProtocol>
You mentioned 'allow' means passing from client? Which client?
If JavaScript, you can do something like this.
$.ajax({
type: 'GET',
url: '/api/values',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
headers: { 'X-My-Secret-Token': 'Token' },
success: function (data) {
}
});
If .NET client, you can do something like this.
string url = "http://www.myurl/api/values";
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-My-Secret-Token", "Token");
var message = client.GetAsync(url).Result;
In Web API, you can read the header in HttpRequestMessage object from any component in the pipeline. For example, you can read the header from a handler like this.
public class MyHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var headers = request.Headers;
if (headers.Contains("X-My-Secret-Token"))
{
string token = headers.GetValues("X-My-Secret-Token").First();
}
}
}
Related
I'm trying to call my Web API Function from an AJAX POST call but keep getting a 405 Error. I've been looking but only been finding solutions saying to Enable CORS, which I've done, but to no avail. For now, I'm just trying to display the data in html. The user enters in an Order Number and that fills in the parameter for the Web API Function. Can anyone tell me what's going wrong?
My Web API Function:
<Route("{ordNbr}/contents")>
<HttpGet>
Public Function GetOrderContents(ByVal ordNbr As String) As SPFolderOver
Dim retValue As ReturnVal
retValue = GetOrderInformation(ordNbr)
Dim sp = New Sharepoint()
Dim t = sp.GetOrderContent(retValue.Year, retValue.SONumber)
Dim contentFolder = New SPFolderOver()
contentFolder = SPFolderOver.LoadFolder(t)
contentFolder.FolderName = t.FullPath
Return contentFolder
End Function
My AJAX call:
function GetOrder() {
var order = document.getElementById("orderNbr").value;
$.ajax({
cache: false,
type: "POST",
url: "http://localhost:54754/orders/{ordNbr}/contents",
data: { 'ordNbr': order },
success: function (data) {
$("#orderContents").html(data);
}
});
};
In my global.asax
Protected Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*")
If (HttpContext.Current.Request.HttpMethod = "OPTIONS") Then
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache")
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept")
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000")
HttpContext.Current.Response.End()
End If
End Sub
In my Web.config
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Olaround-Debug-Mode, Authorization, Accept" />
<remove name="Access-Control-Allow-Headers" />
<add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" />
</customHeaders>
</httpProtocol>
Glad you where able to debug using the Network tab. As a note, I recommend naming the JSON response response to make the distinction with the input data.
function GetOrder() {
var order = document.getElementById("orderNbr").value;
$.ajax({
type: "GET",
data: { 'ordNbr': order },
url: "http://localhost:54754/orders/{ordNbr}/contents)",
cache: false,
success: function (response) {
$("#orderContents").html(response);
},
error: function (err) {
alert("Error: " + err.errorText);
}
});
}
My following code is working fine and I am able to call API
$.ajax({
url: "http://localhost:57786/mvc/create",
method: "POST",
data: { FirstName: "ABC", LastName: "XYZ" },
success: function (data) {
alert("Success");
},
error: function (statusText, error) {
alert("Error");
}
});
But following code is not working and I am not able to call API
$.ajax({
url: "http://localhost:57786/mvc/create",
method: "POST",
data: JSON.stringify({ FirstName: "ABC", LastName: "XYZ" }),
contentType: "application/json; charset=utf-8",
success: function (data) {
alert("Success");
},
error: function (statusText, error) {
alert("Error");
}
});
Here is API code
[EnableCors("*","*","*")]
public class MVCController : Controller
{
// POST: MVC/Create
[HttpPost]
public ActionResult Create(MyData value)
{
//My Code
}
}
I am getting response The response had HTTP status code 404.
Why Ajax call is failing when I use contentType to application/json?
Had similar issues and i fixed it by adding some configurations in the system.webserver in web.config or you can write it as a custom filter attribute and then register it in filterconfig.cs in App_start folder.
<system.webserver>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT,DELETE,OPTIONS"/>
</customHeaders>
</httpProtocol>
</system.webserver>
<--this is for the web,config-->
or for the filterconfig.cs you can write a custom filter and override the ActionFilterAttribute but note that the challenge with this is that any action such as /token to generate an authorization token might fail because it does not satisfy the onActionExecuting method, so maybe you might want to go with the web.config
public class CustomHeaderAttributeFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//add in your custom headers
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type");
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS");
base.OnActionExecuting(filterContext);
}
public void OnException(ExceptionContext filterContext)
{
//do some cool exception handling here
}
}
}
I have a simple web service I debbug this and have a correct answer, the code is:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public String GetUserId()
{
var windowsUserDomain = System.Web.HttpContext.Current.User.Identity.Name;
var windowsUser = windowsUserDomain.Split('\\')[1];
IUser user = Zamba.Core.UserBusiness.GetUserByname(windowsUser);
//this.Context.Response.ContentType = "application/json; charset=utf-8";
//JavaScriptSerializer jsonSerialiser = new JavaScriptSerializer();
//return jsonSerialiser.Serialize(jsonList);
return Newtonsoft.Json.JsonConvert.SerializeObject(user);
}
When I open this WS in Chrome I have this code:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<string xmlns="http://tempuri.org/">
{"Password":"","Crdate":"0001-01-01T00:00:00","Lmoddate":"2014-04-16T00:00:00","Expirationtime":0,"AddressBook":"","Expiredate":"20/07/2005","Nombres":"Dl","Apellidos":"Sri","puesto":"CLAIMS","telefono":"53","firma":"","Picture":"\\\\server2008\\Volumenes\\inDanil.jpg","ConnectionId":0,"WFLic":false,"eMail":{"Type":1,"Servidor":"","Base":"","Mail":"mauso#arc.com.ar","UserName":"mroc.com.ar","ProveedorSMTP":"smtp.gmail.com","Puerto":57,"Password":""},"Groups":[{"IsFull":false,"IsLoaded":false,"State":0,"Type":1,"Description":"","Users":[],"CreateDate":"","PictureId1":0,"Name":"* CLAIMS","ID":2145}],"PictureId1":0,"Type":0,"Description":"Marsh S.A.","State":1,"IsFull":false,"IsLoaded":false,"MailConfigLoaded":false,"Name":"sta","ID":258}
</string>
But when I call this WS in JS with AJAX in this mode:
$.ajax({
type: "GET",
async: false,
url: "Services/UsersInfo.asmx/GetUserId",
success: function (d) {
thisUserId = d.User;
}
});
d = a document in HTML, not a JSON response, I put in my web.config this code:
<add name="ScriptHandlerFactory"
verb="*" path="*.asmx"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
resourceType="Unspecified" />
But every time this return a document and not a JSON response, I cant do "d.data" or $.JSON(d) because d is a document.
How I can configure my WS, AJAX call or Web Config? Thanks
I'm having trouble calling my web api with authentication. It works fine if I leave it out and call methods that don't need authentication.
You guys see anything off in this code?
Here is my ajax call to the server.
jQuery.support.cors = true;
function GetAllPlayers() {
$.ajax({
type: "GET",
url: webServiceUrl + "/api/Player/GetAllPlayers",
beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + $.cookie("fanaTok")); },
success: function (result) {
//TODO handle success
},
error: function (xhr, ajaxOptions, thrownError) {
//TODO Handle error
}
});
}
And here is my web.config
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, Authorization" />
<add name="Access-Control-Allow-Methods" value="GET,POST" />
</customHeaders>
</httpProtocol>
Calling to localhost
The error message:
OPTIONS /api/Player/GetAllPlayers 405 (Method Not Allowed)
OPTIONS/api/Player/GetAllPlayers Invalid HTTP status code 405
XMLHttpRequest cannot load/api/Player/GetAllPlayers. Invalid HTTP status code 405
I finally figured out what was wrong.
The web api did not accept OPTIONS call to the server to verify if the custom authentication header was allowed.
I came across an article where this OPTIONS problem is fixed
http://www.jefclaes.be/2012/09/supporting-options-verb-in-aspnet-web.html
It took me a very long time to figure this out, I hope this helps.
I already worked with web API and had a lot of problems like posting multiple parameters. I upgraded to WebApi2 to use routing attributes and now have problems like:
"message":"The requested resource does not support http method 'DELETE'."
I spent all day searching Stack Overflow and the web to solve the problem:
Removed webdav
In http protocol allow all get,put,post,delete
Added the [HTTPDelete] attribute
Added name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0"
Searched Google for the necessary help here
Can someone please guide me on this?
I had the same problem. Adding the below code to your web.config should fix the problem under the system.webserver section:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
I had the same problem, because my controller was like this:
[HttpDelete]
public HttpResponseMessage Delete(string Id)
{
....
}
And on the client I used the send the ID as request body:
var url = '/api/upload';
var data = JSON.stringify({ 'Id': id }); // <-- In the body
$.ajax({
url: url,
type: 'DELETE',
data: data, // <-- in the body
contentType: 'application/json'
})
When I changed the client to use it as URL parameter instead it worked:
var url = '/api/upload/' + id; // <- In the URL
$.ajax({
url: url,
type: 'DELETE',
contentType: 'application/json'
});
The JavaScript code for the DELETE verb must be like this:
$.ajax({
**url: "/api/SomeController/" + id,**
type: "DELETE",
dataType: "json",
success: function(data, statusText) {
alert(data);
},
error: function(request, textStatus, error) {
alert(error);
debugger;
}
});
Do NOT use something like this,
...
data: {id:id}
...
as when you are using the POST method.