How to invoke WebApi Controller through URL in ASP.Net MVC Project - asp.net-mvc

How to invoke the WepApi Controller Action in browser URL, Below is the Action Method in APIController.
public virtual HttpResponseMessage Export(string ABC, string product, string Release, bool includeInheritedData = false)
{
}

you can define route path and name for web api methods. Using that route can access a API controller action if it is simple Get call and has Anonymous access.
For example:
Suppose this a method in your API controller:
[HttpGet,AllowAnonymous][Route("api/register")]
public void Register()
{
}
You can access it in the URL like: localhost/api/register from browser.This is a simple example to explain thing in simple terms. There are lot of other things involved accessing API methods depending upon various factors like security, requirements etc.

Already its predefined in Appstart/WebApiConfig.cs for WebApi controllers they were using like below.
config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = #"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
config.Routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
config.Routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });

Related

How do I form the URL to call this WebAPI function?

I have this controller in an MVC 5 WebAPI application and I can't seem to figure out how to form the URL to call it. I keep getting a 404. tried .../ssa, /ssa/ssamedians, /ssa/ssamedians?titles=abc... What am I missing?
public class ssaController : ApiController
{
public IHttpActionResult getSsaMedians(string Titles = "")
{
SsaDB db = new SsaDB();
try
{
IEnumerable<Title_Medians> medians = db.getTitleMedians(Titles, null, null);
System.Web.HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");
return Ok(medians);
}
catch
{
return NotFound();
}
}
There are also Actions called getSsaMediansByAaa() and getSsaMediansByBbb(). Once I got rid of the api/ in the routeTemplate, I now get a "Multiple actions were found that match the request".
Open your WebApiConfig.cs file and add this:
config.Routes.MapHttpRoute(
name: "SSATitles",
routeTemplate: "api/{controller}/{action}/{Titles}",
defaults: new { controller = "ssa", action = "getSsaMedians", Titles = UrlParameter.Optional }
);
For more information on webapi routing look here:
http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
You have an parameter in your method, that means that you need to add an extra link in your url.
Examlple.com/DirToApi/getSsaMedians/YourString
You may also want to check your RouteConfig file in your App_Start

Redirect with ASP.NET MVC MapRoute

On my site, I have moved some images from one folder to another.
Now, when I receive a request for old images '/old_folder/images/*' I want to make a permanent redirect to new folder with these images '/new_folder/images/*'
For example:
/old_folder/images/image1.png => /new_folder/images/image1.png
/old_folder/images/image2.jpg => /new_folder/images/image2.jpg
I have added a simple redirect controller
public class RedirectController : Controller
{
public ActionResult Index(string path)
{
return RedirectPermanent(path);
}
}
Now I need to setup proper routing, but I don't know how to pass the path part to the path parameter.
routes.MapRoute("ImagesFix", "/old_folder/images/{*pathInfo}", new { controller = "Redirect", action = "Index", path="/upload/images/????" });
Thanks
I would do in next way
routes.MapRoute("ImagesFix", "/old_folder/images/{path}", new { controller = "Redirect", action = "Index" });
and in controller like that
public class RedirectController : Controller
{
public ActionResult Index(string path)
{
return RedirectPermanent("/upload/images/" + path);
}
}
first download and install RouteMagic package from this link , then redirect your old address to the new address Like the below code :
var NewPath = routes.MapRoute("new", "new_folder/images/{controller}/{action}");
var OldPath = routes.MapRoute("new", "old_folder/images/{controller}/{action}");
routes.Redirect(OldPath ).To(NewPath );
for more information please check out the following link
Redirecting Routes To Maintain Persistent URLs
Answer above using RouteMagic is a good idea, but the example code is wrong (it's included in Phil's post as a bad example).
From the RouteMagic Github demo site global.asax.cs:
// Redirect From Old Route to New route
var targetRoute = routes.Map("target", "yo/{id}/{action}", new { controller = "Home" });
routes.Redirect(r => r.MapRoute("legacy", "foo/{id}/baz/{action}")).To(targetRoute, new { id = "123", action = "index" });
If you specify two routes, you will be setting up an extra mapping that will catch URLs which you don't want.

How can i map all actions to C# class not ASP?

I want map all urls like /Home/User or /Home/About or /Home/Register or ... to c# page like this:
for example User.cs Page is like this:
public class User
{
public string run(UrlParameter id){
return "Hello World";
}
}
i want when user send request for /Home/User .. Call Run function of User Class and show return value to user. How can i do that in ASP MVC?
can i do this with change routes in RouteConfig? now current of my MVC routes is:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
and when i call some url program run an asp page in view folder as default of MVC Project in c#.net.
For more explains:
I have protocol between my client side and server side program that is JSON. i want return string JSON when client ask something and for do it i do not need to asp page for rendering html, i only need to call some function that return JSON to client.
How can i do that with MVC?
I'm assuming your question has two parts.
For the first part : Mapping a url to a page. This is in a sense what routing is. It maps a url to an action, which could be a page or maybe a resource like a picture, or a response like JSON data. Notice it's not always a page, generally a url maps to a resource.
Read the URL routing docs here:
routes.MapRoute(
name: "Default",
url: "/Page1",
defaults: new { controller = "Home", action = "Page1",
id = UrlParameter.Optional }
);
In the above example : fakedomain.com/Page1 will run the Page1 method on the HomeController class and if there isn't any code you've added in there it will search for a Page1.aspx or Page1.cshtml inside your views folder.
I would recommend at this point reading about REST. I suggest this article : How I explained REST to my wife
For your second part : How do you return JSON data. Well you use WebApi. See the docs here.
WebApi allows you to write controllers that return data based on the request. So if your client sends an Ajax request with accept headers set to application/json, WebApi will return JSON.
Also it follows the typical system of asp.net-MVC's controllers, routes and actions.
So to return JSON data that represents products you would have a ProductController that looks like this:
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup",
Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo",
Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer",
Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public Product GetProductById(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return product;
}
}
With asp.net-mvc4 and the default routing setup for WebApi the above controller would respond to the following URLs
This would get all products
/api/products/
This would get call the GetProductById and return ONE product:
/api/products/put_id_here
I would highly recommend getting all the pre-requisites like visual studio and asp.net-mvc from Web Platform installer and then follow this tutorial.

Web API - Multiple POST methods

I am writing a simple web api application. I came to a phase when I need to have two POST methods in my web api controller. One of these methods works and the other does not. My route table looks like this:
config.Routes.MapHttpRoute(
name: "ApiRouteWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then I have my methods defined like this:
[HttpPost]
public bool PostTaskAgain(My3TasksWebAPI.Data.Task task)
{
var oldTask = _db.Task.Where(t => t.Id == task.Id).SingleOrDefault();
oldTask.DoAgain = true;
oldTask.DateUpdated = task.DateUpdated;
if (_db.SetOfTasks.Where(t => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(t.DateCreated, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday) == CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday)).Any())
{
int currentSetOfTasksId = _db.SetOfTasks.OrderBy(s => s.DateCreated).FirstOrDefault().Id;
My3TasksWebAPI.Data.Task newTask = new Data.Task() { CreatedBy = oldTask.CreatedBy, DateCreated = oldTask.DateCreated, DateUpdated = null, DoAgain = false, Notes = string.Empty, SetOfTasksId = currentSetOfTasksId, Status = false, Title = oldTask.Title, UserId = oldTask.UserId };
_db.Task.Add(newTask);
}
_db.SaveChanges();
return true;
}
// Post api/values/PostSetOfTasks/{setOfTasks}
[HttpPost]
public bool PostSetOfTasks(My3TasksWebAPI.Data.SetOfTasks setOfTasks)
{
_db.SetOfTasks.Add(setOfTasks);
_db.SaveChanges();
return true;
}
When I try to call PostTaskAgain I get an internal server error. I think that it might be the routing table but I am not sure how to handle two post methods.
I call the web api from my asp.net mvc application like this:
HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostSetOfTasks", model.SetOfTasks).Result;
and
HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostTaskAgain", taskToPost).Result;
That means that I include the actions.
Working with POST in webapi can be tricky though conincidently, your issue turned out to be trivial. However, for those who may stumble upon this page:
I will focus specifically on POST as dealing with GET is trivial. I don't think many would be searching around for resolving an issue with GET with webapis. Anyways..
If your question is - In MVC Web Api, how to-
- Use custom action method names other than the generic HTTP verbs?
- Perform multiple posts?
- Post multiple simple types?
- Post complex types via jQuery?
Then the following solutions may help:
First, to use Custom Action Methods in Web API, add a web api route as:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}");
}
And they you may create action methods like:
[HttpPost]
public string TestMethod([FromBody]string value)
{
return "Hello from http post web api controller: " + value;
}
Now, fire the following jQuery from your browser console
$.ajax({
type: 'POST',
url: 'http://localhost:33649/api/TestApi/TestMethod',
data: {'':'hello'},
contentType: 'application/x-www-form-urlencoded',
dataType: 'json',
success: function(data){ console.log(data) }
});
Second, to perform multiple posts,
It is simple, create multiple action methods and decorate with the [HttpPost] attrib.
Use the [ActionName("MyAction")] to assign custom names, etc.
Will come to jQuery in the fourth point below
Third,
First of all, posting multiple SIMPLE types in a single action is not possible and there is a special format to post a single simple type (except for passing the parameter in the query string or REST style).
This was the point that had me banging my head with Rest Clients and hunting around the web for almost 5 hours and eventually, the following URL helped me. Will still quote the contents for the link may turn dead!
Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"na#Turbo.Tina"}
http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api
Anyway, let us get over that story. Moving on:
Fourth, posting complex types via jQuery, ofcourse, $.ajax() is going to promptly come in the role:
Let us say the action method accepts a Person object which had an id and a name. So, from javascript:
var person = { PersonId:1, Name:"James" }
$.ajax({
type: 'POST',
url: 'http://mydomain/api/TestApi/TestMethod',
data: JSON.stringify(person),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data){ console.log(data) }
});
And the action will look like:
[HttpPost]
public string TestMethod(Person person)
{
return "Hello from http post web api controller: " + person.Name;
}
All of the above, worked for me!!
Cheers!
There was a problem with my LINQ query.
The response from the server was: {"$id":"1","Message":"An error has occurred.","ExceptionMessage":"LINQ to Entities does not recognize the method 'Int32 GetWeekOfYear(System.DateTime, System.Globalization.CalendarWeekRule, System.DayOfWeek)' method, and this method cannot be translated into a store expression.","ExceptionType":"System.NotSupportedException","StackTrace":" at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTransl‌​ator.Translate(ExpressionConverter parent, MethodCall....
After correcting the linq query everything is working fine. Visual studio was fine about me doing the linq query wrong.

How to route PUT and DELETE requests for the same url to different controller methods

I was searching for an answer to this question, and found this question, which is indeed very similar. However the solutions(s) posted there don't seem to be working for me... I wonder if it has to do with the question's age.
Given the following URL:
/my/items/6
I want HTTP PUT requests for this URL to be handled by one action method, and HTTP DELETE requests to be handled by another action method. Below are the routes I defined (note these are based in an area, so context is an AreaRegistrationContext instance, if that matters):
context.MapRoute(null,
"my/items/{id}",
new { area = "AreaName", controller = "ControllerName", action = "Replace" },
new
{
httpMethod = new HttpMethodConstraint("POST", "PUT"),
}
);
context.MapRoute(null,
"my/items/{id}",
new { area = "AreaName", controller = "ControllerName", action = "Destroy" },
new
{
httpMethod = new HttpMethodConstraint("POST", "DELETE"),
}
);
URL generation works fine with both of these routes, however there are problems when routing incoming requests. Only the first-declared route correctly maps to its respective action.
I dug into the HttpMethodConstraint source code and discovered that it does not care about the "X-HTTP-Method-Override" parameter, only HttpContext.Request.HttpMethod.
I was able to solve this problem with the following custom route constraint class:
public class HttpMethodOverrideConstraint : HttpMethodConstraint
{
public HttpMethodOverrideConstraint(params string[] allowedMethods)
: base(allowedMethods) { }
protected override bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
var methodOverride = httpContext.Request
.Unvalidated().Form["X-HTTP-Method-Override"];
if (methodOverride == null)
return base.Match(httpContext, route, parameterName,
values, routeDirection);
return
AllowedMethods.Any(m =>
string.Equals(m, httpContext.Request.HttpMethod,
StringComparison.OrdinalIgnoreCase))
&&
AllowedMethods.Any(m =>
string.Equals(m, methodOverride,
StringComparison.OrdinalIgnoreCase))
;
}
}
...and these route definitions:
context.MapRoute(null,
"my/items/{id}",
new { area = "AreaName", controller = "ControllerName", action = "Replace" },
new
{
httpMethod = new HttpMethodOverrideConstraint("POST", "PUT"),
}
);
context.MapRoute(null,
"my/items/{id}",
new { area = "AreaName", controller = "ControllerName", action = "Destroy" },
new
{
httpMethod = new HttpMethodOverrideConstraint("POST", "DELETE"),
}
);
My question: is it really necessary to have a custom route constraint to accomplish this? Or is there any way to make it work out-of-the-box with standard MVC & routing classes?
Action filters are your friend...
HttpDeleteAttribute, HttpPutAttribute, HttpPostAttribute, HttpGetAttribute

Resources