Calling the home controller action using ajax - asp.net-mvc-3

I have an 'Index' action within my home controller which responds to the url '/'. The action also has an optional 'id' parameter...
[HttpGet]
public ViewResultBase Index(int id = -1)
{
....
}
the routing for this is...
routes.MapRoute("Home",
"",
new { controller = "Home", action = "Index", id = -1 } );
If I try to call this action using ajax...
$.get(
'#Url.Action("Index", "Home")',
{ id: 20 },
function (response) {
});
the call fails as the url is /?id=20
Is it possible to force the Url.Action to include the controller and action names, as when I do this...
'#Url.Action("Index", "Home")' + 'Home/Index'
all works fine, or do I need to correct my routing?

You dont need to make a special route for your Action method like so. The default route:
{controller}/{action}/{id},
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
Handles that case already; when you request '/' on your server, you should get sent to your Home/Index action method. You should remove the custom route you have specified and let the default route send you to the correct destination.

Related

Ajax calls stop working while using MVC Custom routes

I have defined custom routes for user friendly URLs.
But unable to call default route using ajax or on using Ajax.BeginForm() On removing custom routes, all works perfectly.
This is my RouteConfig.cs
//product view route
routes.MapRoute(
name: "ProductView",
url: "product/{product_name}/{id}",
new { controller = "Product", action = "View", product_name = UrlParameter.Optional, id = UrlParameter.Optional },
new[] { "NoveltyApp.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "NoveltyApp.Controllers" }
);
Product View URL: http://localhost:56379/product/Camlin-Kokuyo-Acrylic-Color-Box---9ml-Tubes-1/1
ProductController.cs
public string ProductReviews()
{
return "Product review list";
}
Ajax call from Product view
<button type="button" class="btn btn-thm nf-pr-vi__btn" onclick="reviews()">Reviews</button>
<script>
function reviews() {
$.ajax({
url: '/Product/ProductReviews',
type: 'GET',
success: function (data) {
alert(data);
}
});
}
</script>
But on click button controller action not getting hit. Please help me out with a solution.

Using AJAX with MVC 5 and Umbraco

I need to use ajax in a partial view to call a function in a mvc controller to return a calculation.
FYI, I am using MVC 5 and Umbraco 7.
I currently have the ajax code within the partial view (will want to move this to a js file at some point).
Here is the ajax code:
function GetTime(name) {
var result = "";
$.ajax({
url: '/TimeDifference/GetTimeDifference',
//url: '#Url.Action("GetTimeDifference", "TimeDifference")',
type: 'GET',
//data: JSON.stringify({ location: name }),
data: ({ location: name }),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
async: false,
cache: false,
success: function (msg) {
result = msg;
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
}
});
return result;
}
Here is the Controller:
public class TimeDifferenceController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpGet]
public JsonResult GetTimeDifference(string location)
{
DateTime utc = DateTime.UtcNow;
string timeZoneName = GetTimeZoneName(location);
TimeZoneInfo gmt = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
TimeZoneInfo local = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
TimeSpan utcOffset = gmt.GetUtcOffset(utc);
TimeSpan localOffset = local.GetUtcOffset(utc);
TimeSpan difference = localOffset - utcOffset;
return Json(Convert.ToInt16(difference.TotalMinutes),JsonRequestBehavior.AllowGet);
}
}
The above code gives me a 404 Not Found Error:
Request URL:http://localhost:100/TimeDifference/GetTimeDifference?location=BVI&_=1511949514552
Request Method:GET
Status Code:404 Not Found
Remote Address:[::1]:100
If I use:
url: '#Url.Action("GetTimeDifference", "TimeDifference")'
The #Url.Action("GetTimeDifference", "TimeDifference") is Null so it doesn't go anywhere.
I have also tried:
#Html.Hidden("URLName", Url.Action("GetTimeDifference", "TimeDifference"))
...
url: $("#URLName").val()
Url is still Null.
I have added entries in to the Global.asax.cs for routing i.e.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "TimeDifference", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
This doesn't seem to do anything.
I have gone through a lot of the questions raised previously and amended as per suggestions but nothing seems to work.
As I am new to this I'm sure it something very simple I am missing.
Many thanks,
HH
Your controller won't be wired automatically, and I don't think the global.asax.cs file will work either. You can either register a custom route for your controller in an Umbraco Startup Handler: https://our.umbraco.org/documentation/reference/routing/custom-routes or you can create your controller as an Umbraco WebApi Controller, which is designed for stuff like this: https://our.umbraco.org/documentation/Reference/Routing/WebApi/.
Umbraco WebAPI controllers get wired in automatically and will return either JSON or XML automatically depending on what the calling client asks for.

Call web API string parameter

I have this function
[System.Web.Http.HttpGet]
[System.Web.Http.ActionName("StartProcess")]
public object StartProcess(string items)
{
//do stuff
}
trying to call with
$.ajax({
url: '/api/Details/StartProcess',
type: 'get',
contentType: 'application/json',
data: items,
success: function() {
logger.log('Successful', "", "", true);
},
error: function(error) {
var jsonValue = jQuery.parseJSON(error.responseText);
});
Keep getting 404 error. The rest of my calls work but this is the first one that I need to send a parameter.
items is just a comma delimited string.
this is my route info.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id=Urlameter.Optional }
);
Any ideas what I am missing?
you are getting 404 error because your routing table is not able to resolve the url "/api/Details/StartProcess"
In order to make the WebAPI routing work you need to modify the "MapHttpRoute()" function of route collection and not the "MapRoute()"
So please change the API routing as below (assuming you are using default api) and it should work fine.
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional }
);
The parameter in Web API needs to follow the parameter in routing config.
In your example the easiest would be to change string items to string id.
Alternatly you could add api/{controller}/{action}/{items} to the route config.
Also, if you don't fancy changing your API route config (which would lead to minor complications with calling simple Get and Put methods) you can change your controller action annotation from
[System.Web.Http.ActionName("StartProcess")]
to
[Route("StartProcess/{items}")]
Also, you'll need to annotate your controller with:
[RoutePrefix("api/details")]

WebApi call fails for other than the default route

I have an Mvc3 project that includes both Mvc and Api controllers. When I run the application without specifying the "controller/action", the "Default" route is selected and the "home/index" page is rendered. When that page runs, an Ajax call is made using url: "api/controller", returning json, which is then used to populate a table on the page.
<script type="text/javascript">
$(function () {
var $products = $("#products");
$.ajax({
url: "api/products",
contentType: "json",
success: function (data) {
$.each(data, function (index, item) {
$products.append("<tr><td>" + item.ProductCode + "</td>" +
"<td>" + item.Description + "</td>");
});
}
});
});
</script>
However, when a request is made to the same page specifying the "controller/action", as in "localhost/home/index", the Ajax call is translated to "/home/api/controller" and of course the request cannot complete or return any results, since the ApiController cannot be found.
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Considering that it must be a routing issue, I proceeded to resolve this by adding a route:
routes.MapHttpRoute(
"HomeApi",
"home/api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
This was successful. As was my next change to:
routes.MapHttpRoute(
"AnyApi",
"{folder}/api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
Which also works but leaves me somewhat skeptical as to whether it is the correct way to handle combining WebApi with Mvc.
Is this the correct way to handle this? Or are there better alternatives?
Considering that it must be a routing issue, I proceeded to resolve this by adding a route:
No, that's not a routing issue at all. Your routes are perfectly fine:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Your issue stems from the fact that you have hardcoded the url in your javascript instead of using url helpers to generate it. You should absolutely never hardcode an url inside an ASP.NET MVC application. You should always use url helpers.
So:
<script type="text/javascript">
$(function () {
var $products = $("#products");
var url = '#Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" })';
$.ajax({
url: url,
success: function (data) {
$.each(data, function (index, item) {
$products.append("<tr><td>" + item.ProductCode + "</td>" +
"<td>" + item.Description + "</td>");
});
}
});
});
</script>
Also notice that I have removed the contentType: 'json' from your AJAX call because first the correct content type is contentType: 'application/json' and second in this case you are not sending any data in the request, so you shouldn't be setting it to application/json.
There's no need to add a route there -- you can specify the API URL so that it will always work:
/api/controller
In some cases you may need to use the Url.RouteUrl helper to create URLs explicitly based on the route (by route name and/or route values). For example, this would specify the route named "DefaultApi" with controller=products:
#Url.RouteUrl("DefaultApi", new { controller = "products" })

Do i have to list all controller functions?

Do i have to list all controller functions in Global.asax.cs file?
Im creating a api for my workout and have created the controller WorkoutController. It has the action AddWorkout that takes some parameters, for instance username, password, duration and type. Two first are string, two last is ints.
Now, do i need to create a route for it? And every action with different action signature? Why could it not fall in under the default route? Calling it would break if i dont supply the correct variables, but i know what im doing :D
routes.MapRoute(
"AddWorkout", // Route name
"Workout/AddWorkout/", // URL with parameters
new { controller = "Workout", action = "AddWorkout" } // Parameter defaults
);
??? :D ???
You can easily create a REST Api:
routes.MapRoute(
"Workout", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
and use for example of your Workout:
public class WorkoutController : Controller
{
public ActionResult Index()
{
return RedirectToAction("Index", "Help");
}
[HttpPost]
public ActionResult Workout(FormCollection form)
{
// HTTP POST: ADD Workout
// process form and return JSON
return Json(myObject);
}
[HttpDelete]
public ActionResult Workout(string id)
{
// HTTP DELETE: REMOVE Workout
// process form and return JSON
return Json(myObject);
}
[HttpGet]
public ActionResult Workout(string id)
{
// HTTP GET: GET Workout
// process form and return JSON
return Json(myObject);
}
}
But I would suggest you to use WCF though :)
From a client side:
$.ajax({
type: "POST",
url: "/Workout/Workout",
data: {
'type': '123456',
'height': '171'
}
success: function(msg){
alert( "Data Saved: " + msg );
}
});
$.ajax({
type: "DELETE",
url: "/Workout/Workout",
data: { 'id': '123456' }
success: function(msg){
alert( "Data Saved: " + msg );
}
});
$.get("/Workout/Workout", { 'id': '123456' }, function(msg){
alert( "Data Saved: " + msg );
});
remember to create a Login method that you would send a token that is required in all actions, so you know that the user manipulating your data is real.
Read this.
The "Url" property on the Route class defines the Url matching rule
that should be used to evaluate if a route rule applies to a
particular incoming request.
No, you don't have to do this at all. The default route looks at what methods are defined and will figure out what to call as long as your parameters line up to some method on the controller.

Resources