405 method not allowed MVC 4 POST was working before - asp.net-mvc

I have a really baffling issue with a customer site. We developed a C# MVC 4.0 application that's running in a subdirectory from another ASP.net application. We use a lot of Ajax calls from JQuery to controllers. Recently there's been an issue where a particular method on a controller has started returning "405 method not allowed" when doing a POST. This method is no different from any of the numerous other Ajax methods which are fine.
Edited to provide code:
Here's the offending function:
JavaScript:
function populateCitiesLike(cityTerm, fnInitialCityNames) {
var serviceBase = 'ProjectCities/';
var cityData = { term: cityTerm };
$.ajax({
type: "POST",
data: JSON.stringify(cityData),
url: serviceBase + "GetCitiesThatStartWith/",
contentType: "application/json",
success: function (result) {
$("#cityCheckboxes").empty();
if (result.length === 0) {
return;
}
addCityCheckboxes(result);
if (fnInitialCityNames != null)
fnInitialCityNames();
},
error: function () {
alert("We have an error");
}
});
}
c# controller :
[AjaxOnly,HttpPost]
public ActionResult GetCitiesThatStartWith(string term)
{
List<string> dbCities = null;
List<Cities> cityList = new List<Cities>();
dbCities = _reposProject.GetCitiesThatStartWith(term);
cityList = GetJsonFormatForCityList(dbCities);
// return Json(result);
return Json(cityList, JsonRequestBehavior.AllowGet);
}
I copied the entire web application and created a new subdirectory just to see what would happen. So for example the current application is running under main\A directory and now the cloned application is running under main\B. the method GetCitiesThatStartWith running under main\A that returns a 405 but the same method under main\B works. However there is one specific method called GetCitiesFromRegion that is always failing on both. That particular method used to work.
I don't think it's a code issue because why would one work and the other not. Resetting IIS does not work either. I can add test methods to the controller and call them from a test Ajax page and sometimes they fail and sometimes not. Once they fail with that particular method name I can no longer make it work. It's almost as if IIS remembers that the method failed and is caching the error.
updated
After spending more time with it I have discovered 2 issues. One issue is that the controllers constructor was throwing an exception because it was not authenticated at that point. I have resolved that issue.
The other issue which is baffling is that I could not get GetCitiesThatStartWith to work and a few other methods. I renamed them by appending V2 to the end of the method name and now they work.
Why would renaming a method on a controller make it work? I suspect that once the method gets an error and it stops working then I have to rename the method. Something about throwing an exception in the controller can be fatal to your method name apparently.

I think this will help you:-
I have changed the method name to CitiesThatStartWith by default it will be mapped with Get request because you are using GetCitiesThatStartWith.
Controller code
[AjaxOnly,HttpPost]
public ActionResult CitiesThatStartWith(string term)
{
List<string> dbCities = null;
List<Cities> cityList = new List<Cities>();
dbCities = _reposProject.GetCitiesThatStartWith(term);
cityList = GetJsonFormatForCityList(dbCities);
// return Json(result);
return Json(cityList, JsonRequestBehavior.AllowGet);
}
Javascript code
function populateCitiesLike(cityTerm, fnInitialCityNames) {
var serviceBase = 'ProjectCities/';
var cityData = { term: cityTerm };
$.ajax({
type: "POST",
data: JSON.stringify(cityData),
url: serviceBase + "CitiesThatStartWith/",
contentType: "application/json",
success: function (result) {
$("#cityCheckboxes").empty();
if (result.length === 0) {
return;
}
addCityCheckboxes(result);
if (fnInitialCityNames != null)
fnInitialCityNames();
},
error: function () {
alert("We have an error");
}
});
}

Related

Calling controller method with a get type not working in ASP.NET MVC

I have a java script function that calling a controller method using Ajax, this call should get me the user profile page, I have a controller for this purpose. When I run the program and fire the java script function it's trigger the controller and every thing is good but when the debugging has ended no changes happens and the view doesn't present in the screen.
I tracked the call and every thing is working fine, passing parameter and reaching the method in the controller.
Note: the view which has the JS call related to a different controller.
View contain java script call:
<td onclick="ViewProfile('#item.CustomerId')"></td>
Java script file
function ViewProfile(id) {
console.log("sucsses");
$.ajax({
type:"GET",
url: "/ViewUserProfile/Index",
data: { "userId": id }
});
};
Controller: ViewUserProfileController
public ActionResult Index(string userId)
{
var ProfileInformation = new UserProfileVM
{
//some logic here
};
return View(ProfileInformation);
}
You are fetching ViewUserProfile in $.ajax but you are not using .done(function() { }) to process the result you receive from that call.
In your case I would simply suggest to use window.location.href in ViewUserProfile() as below.
function ViewProfile(id) {
window.location.href = "/ViewUserProfile/Index?userId=" + id;
}

Breeze EntityQuery.from() withParameters POST to API not working

I have this peace of code :
function getSopMatches(data) {
return EntityQuery.from('GetSopMatches')
.withParameters({
$method: 'POST',
$encoding: 'JSON',
$data: data
})
.using(manager).execute()
.then(success)
.catch(_queryFailed);
function success(response) {
return response.results;
}
}
and it is called through this :
playerService.getSopMatches({ playerId: vm.player.id, competitionId: career.competitionId, seasonId: career.seasonId, teamId: career.teamId }).then(function (results) { //do something with it });
In my MVC controller (BreezeController) the method is like :
[HttpPost]
public IQueryable<object> GetSopMatches(SopMatch sop)
{
//this method is not called, I get a 405 Method not Allowed
}
Somehow, the actual call is a GET, instead of a POST and therefore I get the 405 Method not Allowed error message.
I have other peaces of code in the same project (client side javascript/breeze calls and server side mvc controller methods) that do work.
Does anybody knows what I'm doing wrong, or why it is changed to a GET method ?
After a day of trying and failing, I found a solution.
It appeared that in the angular controller I was injecting breeze, and that was causing the issue. When breeze is injected into the controller or service, it messes up the URL of the POST and therefore you receive a 405 (because the URL is changed).

angularjs $compile is not working on production

I am using angularJS in my MVC application and loading a partial using ajax call in angularJS. I am using $compile to compile the html. Everything is working fine on local but it is not working on production. Unexpected error is showing. Below is the code I am using.
Angular Controller:
app.controller("mproductController", ["$scope", "mproductService", "$compile", function ($scope, mproductService, $compile) {
$scope.ShowProdUnitPop = function (val) {
mproductService.ShowProdUnitPop(val).success(function (result) {
debugger;
var snippet = angular.element(result);
$compile(snippet)($scope);
$("#dvAddProd").html(snippet);
$("#dvPopup").modal('show');
});
}
}
Angular Service:
app.service("mproductService", ["$http", function ($http) {
this.ShowProdUnitPop = function () {
var request = $http({
method: "post",
url: "/Home/GetActiveCat"
});
return request;
}}
MVC Controller:
[HttpPost]
public ActionResult AddProduct(int id)
{
ViewBag.ProductCategory = Utility.GetProd(id);
return PartialView("_AddProduct",new Product());
}
Error is throwing on this line:
var snippet = angular.element(result);
$compile(snippet)($scope);
$("#dvAddProd").html(snippet);
$("#dvPopup").modal('show');
It is working on local but not on production. Please help.
Seems like you are using bundling and minification enabled on production server. That is breaking you controller code while you are utilizing that controller and its necessary to have inline array annotation of DI while minifying JS files.
Most possible answer would be you are using $compile by injecting it to controller and using it, That's fine. It seems like you had not followed inline array dependency injection inside your controller.
Also you need to attach compile element to your dvAddProd element, rather than updating html, appending html to DOM will never make angular angular binding on that element. Looks like this code shouldn't be working on any of the environment if it has angular bindings on it.
Controller
app.controller('someCtrl', ['$scope', '$http', '$compile',
function($scope, $http, $compile) {
//you should have controller in this way that would fix your issue
//note I'm using inline array notation of DI
$scope.ShowProdUnitPop = function(val) {
mproductService.ShowProdUnitPop(val).success(function(result) {
debugger;
var snippet = angular.element(result);
var compiledSnippet = $compile(snippet)($scope);
$("#dvAddProd").append(compiledSnippet); //should attach compile element
});
}
}
]);
Visit this link for more Information

Is it possible that MVC is caching my data some place?

I have the following controller action:
public ActionResult Details(string pk)
{
IEnumerable<ContentDetail> model = null;
try
{
model = _content.Details(pk);
if (model.Count() > 0)
{
return PartialView(getView(pk) + "Details", model);
}
}
catch (Exception e)
{
log(e);
}
return Content("No records found");
}
I call this with the following routine:
$.ajax({
cache: false,
url: "/Administration/" + table + "s/Details",
data: { pk: partitionKey },
dataType: 'html',
success: function (responseText) {
$('#detailData').html(responseText);
$(".updatable")
.change(function (e) {
var type = $(this).attr('id').split('_')[0];
updateField(table, $(this), type);
});
$('.dialogLink')
.click(function () {
dialogClick(this);
return false;
});
},
error: function (ajaxContext) {
ajaxOnFailure(ajaxContext)
}
});
What I notice is that sometimes when I put a break point on the first line of the controller action then it does not seem to stop at the breakpoint. Is it possible the results are being cached by MVC and how could I stop this from happening while I debug?
Check for any variation of OutputCache being set on the controller itself or, if present, a base controller all your controllers may inherit from.
I've also noticed IE likes to cache things and found the only way to alleviate this is doing to the developer window and clearing the cache (or ctrl+shift+del)
Try adding cache:false to your .ajax call and see if that has any bearing (jQuery will append a timestamp variable making each call unique). Nevermind, just noticed you have it included. Must be getting late here--sure sign it's bed time when I miss things like this.
Load up fiddler and see if the request is even coming back from the browser. Ideally you'll want I write out no cache headers through one of the many methods mentioned here
Disable browser cache for entire ASP.NET website

Returning an List<> with JsonResult

I am using jQuery to consume my action.
$.ajax({ url: '',
data: 'json',
type: 'post',
dataType: options.dataType,
async: false,
success: function (obj) { returnValue = obj; }
});
now....
if I return this one...
var test1 = Json(new { Message = "Any message here.", Status="True" });
the return on my Ajax call is JUST fine..
BUT.. if i return this one(List of users from EF)
var test2 = Json(IoC.Resolve<IUserService>().GetUsers());
I will get undefined/500 (Internal Server Error).
Now the question is how to properly return a JSON from an object so that jQuery ajax can read it properly?
Thanks
Lee,
Have never seen the usage:
var test2 = Json(IoC.Resolve<IUserService>().GetUsers());
before and am not going to comment. However, you MAY get away with merely adding a .ToList() to the end of the statament, i.e.:
var test2 = Json(IoC.Resolve<IUserService>().GetUsers().ToList());
The reason for the issue is due to the fact that you haven't yet enumerated the object out before attempting to populate the json object, therefore you experience all sorts of latency and object reference problems. By adding ToList() you mitigate these problems as the object is fully enumerated before it hits the Json() method.
it might just work, ... or blow right up :)
public ActionResult MethodName(){
var returnList = IoC.Resolve<IUserService>().GetUsers().ToList();
retun JSON(returnList,JSONRequestBehaviour.AllowGet);
}
jQuery Function
success: function (obj) {
alert(obj.d.ListProperty);
// you can access all the properties you have in the list.
}

Resources