i've been trying my hand on Angularjs + rest and when trying to get the data , i am getting the error - undefined 405 (Method Not Allowed)
main.js --
url:'http://abc.org/angularDemo/rest/demo/studentJson',
type:'GET'}).success(function (sampleData) {
alert("here ... "+sampleData);
$scope.setPagingData(sampleData,page,pageSize);
}).error(function () {
alert("Error getting users.");
});
#Path("/demo")
#XmlRootElement
public class AngularDataObj {
#GET
#Path("/studentJson")
#Produces(MediaType.APPLICATION_JSON)
public List<StudentObj> studentJson(){
List<StudentObj> list = new ArrayList<StudentObj>();
StudentObj obj = new StudentObj();
//Map<String,StudentObj> map = new HashMap<String,StudentObj>();
for(int i=0 ; i< 50; i++){
obj.setName("name"+i);
obj.setAge(20+i);
obj.setId(i);
obj.setLocation("location"+i);
list.add(obj);
//map.put(""+i, obj);
}
return list;
}
}
i am able to see the json object when i directly access this url - http://abc.org/angularDemo/rest/demo/studentJson
Change your web.config, removing the following keys:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
From:
http://www.askamoeba.com/Answer/196/Http-405-Method-Not-Allowed-error-Web-API-Controller-PUT-Request-AngularJs
Regards.
Related
I have a Web API that worked perfectly on development with all kind of HTTP requests (on the same controller), once I moved it to production (shared server, I don't even have access to it) the DELETE requests stopped working (the others are working fine), I get a 404 error:
Requested
URL https://www.example.com:443/Rejected-By-UrlScan~/API/Users/DeleteUser/1
Physical Path d:\xx\yy\example.com\Rejected-By-UrlScan
Logon Method Anonymous
Logon User Anonymous
This is (a part of) the web.config:
<system.web>
<customErrors mode="Off"/>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
The Delete Action:
[Authorize]
[RoutePrefix("Users")]
public class UsersController : ApiController
{
[HttpDelete]
[Route("DeleteUser/{id:int}")]
public void Delete(int id)
{
_UsersRepository.Delete(id);
}
And the AJAX call:
deleteUser = function (id, callback) {
$.ajax({
url: "../API/Users/DeleteUser/" + id,
type: "DELETE",
success: function () {
callback;
}
});
}
WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//create json formatter and remove all others
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
config.Formatters.Remove(config.Formatters.XmlFormatter);
}
An example of a working call on the same Controller:
getUsers = function (callback) {
$.get("../API/Users/GetUsers/", callback);
}
And the Action:
[Route("GetUsers")]
public IEnumerable<User> GetUsers()
{
return _UsersRepository.GetUsers();
}
In your IIS do you have the URLScan extension configured ?
https://www.iis.net/downloads/microsoft/urlscan
UrlScan is a security tool that restricts the types of HTTP requests that IIS will process.
The "Rejected-By-UrlScan" in your URL suggests that the extension may be configured to reject "Delete" requests.
You can ask your Administrator of the Server hosting the IIS about whether Delete requests are configured to be allowed in the IIS.
The URL is wrong in the JS snippet. It should be
deleteUser = function (id, callback) {
$.ajax({
url: "[Application_Path]/Users/DeleteUser/" + id,
type: "DELETE",
success: function () {
callback;
}
});
}
[RoutePrefix("Users")] overrides the default routing, so there should be no "API" in the URL.
You should remove the [Application_Path] and put your virtual directory name or use the #Url.Action
I had to got it to work so I changed the type of the request from DELETE to POST and it works perfectly:
[Authorize]
[RoutePrefix("Users")]
public class UsersController : ApiController
{
[HttpPost]
[Route("DeleteUser/{id:int}")]
public void Delete(int id)
{
_UsersRepository.Delete(id);
}
deleteUser = function (id, callback) {
$.ajax({
url: "../API/Users/DeleteUser/" + id,
type: "POST",
success: function () {
callback;
}
});
}
WebAPI in .net core can elegantly handle Json request, but it seems not able to handle XML content-type natively?
I did some search, and got only the post about this, http://www.strathweb.com/2015/04/asp-net-mvc-6-formatters-xml-browser-requests/
Yet, I tried as below, not successful
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
})
.AddMvcOptions(options =>
{
//var jsonFormatter = options.InputFormatters.First(o => o.GetType() == typeof(JsonInputFormatter));
//if (jsonFormatter != null) { options.InputFormatters.Remove(jsonFormatter); }
options.InputFormatters.Add(new XmlSerializerInputFormatter());
options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
options.RespectBrowserAcceptHeader = true; // false by default
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter(
new System.Xml.XmlWriterSettings
{
ConformanceLevel = System.Xml.ConformanceLevel.Auto,
WriteEndDocumentOnClose = true
}
));
var a = options.FormatterMappings.GetMediaTypeMappingForFormat("text/xml");
})
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters()
;
Below is my controller action
// POST api/values
[HttpPost("Order")]
public string OrderRetrievea([FromBody] OrderRequest request)
{
}
Content-type is set to text/xml.
Xml request:
<?xml version="1.0"?>
<OrderRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.myco.org/ns">
....
</OrderRequest>
It(request)'s always null.
I have a web service defined as:
[ScriptService]
public class LoginController : ApiController
{
[HttpGet]
[WebMethod]
public IEnumerable<string> getUsers()
{
try
{
using (var context = new questionanswerEntities())
{
var users = context.users.ToList();
string[] result = new string[users.Count];
for (int i = 0; i < users.Count; ++i)
{
user u = users[i];
result[i] = u.id + " " + u.name + " " + u.email;
}
return result;
}
}
catch (MySqlException ex)
{
throw (ex);
}
catch (EntityException ex)
{
throw (ex);
}
}
}
I have published this service to my localhost and I am able to call and test it with a browser and the result is:
<ArrayOfstring>
<string>1 Olcay aaa#aaa.com</string>
<string>2 Mukaddes aaa#aaa.com</string>
<string>3 Saduman sadumanertas#gmail.com</string>
<string>4 Bernam bernella#bb.com</string>
<string>8 Bernella bernella#gmail.com</string>
<string>9 Bernella bernella#gmail.com</string>
<string>10 Bernella bernella#gmail.com</string>
<string>11 Bernella bernella#gmail.com</string>
<string>12 Bernella bernella#gmail.com</string>
<string>13 Bernella bernella#gmail.com</string>
<string>14 lala loorrrrr#gmail.com</string>
<string>15 lala loorrrrr#gmail.com</string>
</ArrayOfstring>
What I need is to call this service from JavaScript. I am trying this:
function callService() {
var url = "http://localhost:1903/QATest/login/getUsers";
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader("Content-type", "application/json");
xhr.onload = function () {
var response = xhr.responseText;
console.log("XHR - onload - Result of getUsers: " + response);
document.getElementById('response').innerHTML = "Response: " + response;
};
xhr.onerror = function () {
console.log("XHR - onerror - Web servis cagirilirken hata olustu!");
};
xhr.send();
};
But getting this error:
XMLHttpRequest cannot load http://localhost:1903/QATest/login/getUsers. Invalid HTTP status code 405
My ASP.NET service is hosted on my localhost and client side codes are hosted at my remote host at 'www.olcayertas.com'.
What am I doing wrong?
UPDATE:
I have started this project as ASP.NET Web application and then selected Web API option. So there is no any asmx files as web service projects. But Exposing Web Services to Client Script suggests adding following to client side for ASP.NET web pages:
<asp:ScriptManager runat="server" ID="scriptManager">
<Services>
<asp:ServiceReference
path="~/WebServices/SimpleWebService.asmx" />
</Services>
</asp:ScriptManager>
But I have to call my services using JavaScript from a PHP page.
How can I do that?
You are being blocked because you are attempting a Cross-Origin XMLHttpRequest which fails because of the Same-origin policy
You will need to configure CORS on you local host to allow requests from 'www.olcayertas.com'. With IIS you might just need to add this to the web.config;
<add name="Access-Control-Allow-Origin" value="*" />
Be careful though as this opens up your service to requests from any domain. You should probably only allow requests from 'www.olcayertas.com' if you know this is the only consumer of your web service.
I'm trying to access /elmah.axd in my broswer, but it returns:
{"message":"No HTTP resource was found that matches the request URI 'http://services.domain.com/elmah.axd'."}
The server is local (127.0.0.1) and even on that I have my web.config Elmah settings to secure it this way:
<elmah>
<security allowRemoteAccess="true" />
</elmah>
My WebApiConfig looks like:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Locally only you will be able to see the exception errors
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly;
// Web API routes
config.Routes.IgnoreRoute("elmah", "elmah.axd");
config.Routes.IgnoreRoute("allemah", "elmah.axd/{*pathInfo}");
config.Routes.IgnoreRoute("elmahgeneric", "{resource}.axd/{*everything}");
config.MapHttpAttributeRoutes();
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I even tried ignoring only one route at the time from any of the 3 combinations and no luck.
finally my global.asax looks like this:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Any hint or idea of what I could be missing, would be good.
Thanks in advance, really appreciate your time looking into this.
I finally made it.
By adding to the WebApiConfig.cs file
config.Routes.MapHttpRoute("AXD", "{resource}.axd/{*pathInfo}", null, null, new StopRoutingHandler());
The entire code of the WebApiConfig.cs file looks like this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Locally only you will be able to see the exception errors
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly;
// Web API routes
config.MapHttpAttributeRoutes();
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Routes.MapHttpRoute("AXD", "{resource}.axd/{*pathInfo}", null, null, new StopRoutingHandler());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
And the final change is add this to the global.asax under application_start method
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
Special thanks all who helped me with this issue.
When I added the following in in the global.asax under the application_start method:
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
It did not work until I put it above ...
GlobalConfiguration.Configure(WebApiConfig.Register);
The order of the routes that you add to the Routes property is significant, because the application uses the first route in the collection that matches the URL.
https://msdn.microsoft.com/en-us/library/system.web.routing.routetable.routes(v=vs.110).aspx
The most likely problem is missing handlers to generate the error page.
Ensure the following handlers are configured your web.config file:
<system.web>
...
<httpHandlers>
...
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
<system.webServer>
...
<handlers>
...
<add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</handlers>
With those settings in place you should be able to access elmah.axd and secure it as expected.
You can grab a sample config file that was updated from a fresh project as an example here: https://brutaldev.com/download/30987439.zip
For me adding
config.Routes.IgnoreRoute("axd", "{resource}.axd/{*pathInfo}");
to WebApiConfig was enough.
I had basic SignalR functionality implemented and working in my MVC5/AngularJS application recently, but after shelfing and unshelfing the changes I am now getting an error when the connection is negotiated in $.connection.hub.start().
I've stripped down the code to the very basics, but still get this error. Poking around in the jquery.signalR-2.2.0.js where the negotiate request is made, I found that the result returned from the ajax request to http://localhost:44379/signalr/negotiate?clientProtocol=1.5&connectionData=[] is returning the HTML of the page instead of JSON data!
connection._.negotiateRequest = /* This is on line 659 */ signalR.transports._logic.ajax(connection, {
url: url, // http://localhost:44379/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%5D
error: function (error, statusText) {
// Irrelevant code removed.
},
success: function (result) { // We get here at least...
var res,
keepAliveData,
protocolError,
transports = [],
supportedTransports = [];
try {
res = connection._parseResponse(result); // This fails because result contains HTML.
} catch (error) {
// error.message is "Unexpected token <"
onFailed(signalR._.error(resources.errorParsingNegotiateResponse, error), connection);
return;
}
Here is my javascript for establishing the hub/connection:
$(function () {
var hub = $.connection.testHub;
if (hub)
console.log("SignalR hub initialized.");
$.connection.hub.start().done(function () {
console.log("SignalR connection established.");
}).fail(function (err) {
console.log("Error starting SignalR connection: " + err); // Ends up here.
});
});
And the script references (I have the signalr code in a separate js file named messaging.js):
<script src="~/assets/js/signalr/jquery.signalR-2.2.0.js"></script>
<script src="~/Scripts/messaging/messaging.js"></script>
<script src="~/signalr/hubs"></script>
I don't really understand why the ajax response from signalr/negotiate would be returning HTML instead of JSON. I've stripped down the server side hub code to an empty class with [AllowAnonymous] to ensure nothing in there was causing the problem. I have the app.MapSignalR() call in Startup.cs in place. My first thought, since this occurred after shelfing and unshelfing, was that something didn't make it into the shelf and was lost, but I can't seem to find anything missing...
Anyone have any ideas?
I found the problem while playing with the rules in web.config.
Previously, I had this rule for signalr:
<add input="{REQUEST_URI}" matchType="Pattern" pattern="/signalr/hubs" negate="true" />
Changing the pattern allowed communication with /signalr/negotiate, I think:
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/(signalr)" negate="true"/>
...I have no idea how this worked before.