ASP.NET Routing not working - asp.net-mvc

I am struggling to make Route Prefix working or probably have misunderstanding about Routes in ASP.NET Web API
Here is my code:
public class TestController : ApiController
{
// GET: api/Test
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Test/5
public string Get(int id)
{
return "value";
}
[HttpGet]
[Route("GetValue")]
public string GetValue(int id)
{
return "best";
}
[HttpGet]
[Route("GetValue1")]
public string GetValue1(int test)
{
return "GetValue";
}
}
Here is the status of each call
localhost:52154/api/test/Getvalue1/1 (HTTP Error 404.0 - Not Found)
localhost:52154/api/test/Getvalue1?test=1 (
The webpage cannot be found )
localhost:52154/api/test/Getvalue?id=1 (Works return "value" but does not call the GetValue Method)
localhost:52154/api/test/1 (Works return "value")
localhost:52154/api/test/ (Works return "value1","value2")
Please let me know what to do to make the GetValue1 and GetValue route work. I did update the NuGet pacakge for ASP.NET to Web Api 2.2
WebApiConfig looks like this
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }

Here is the solution which worked for me
public IEnumerable Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Test/5
public string Get(int id)
{
return "value";
}
[HttpGet]
public string GetValue(int id)
{
return "best";
}
[HttpGet]
public string RetriveValue(int test)
{
return "GetValue";
}
courtesy of
How to bypass the exception multiple actions were found in ASP.NET Web API

Use This : [ActionName("Getvalue1")]
hope this works!!

Related

MVC web api with GET and POST Method

how to execute MVC web api method with different name but type is GET and POST. i can't able to execute. it shows error. here is my code.
webapiconfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "get", id = RouteParameter.Optional }
);
Employee controller :
[HttpGet]
public string Test1()
{
return "this is a test1 string";
}
[HttpGet]
public string Test2()
{
return "this is a test2 string";
}
[HttpPost]
public string Test3()
{
return "this is a test3 string";
}
i want to execute both post and get all this method in different scenario. how to do it?
There are two ways to achieve this
Specify different input parameters for methods with same Http Method (HttpGet/ HttPost/HttpPut).
Example -
[HttpGet]
public string Test1(string input)
{
return "this is a test1 string";
}
[HttpGet]
public string Test2()
{
return "this is a test2 string";
}
Specify explicit different routes for each of the method in Controller using multiple HttpGet.
[HttpGet]
[Route("~/mycontroller/action")]
public string Test1(string input)
{
return "this is a test1 string";
}
[HttpGet]
[Route("~/mycontroller/action2")]
public string Test2()
{
return "this is a test2 string";
}

can't figure out routing in asp.net mvc

I'm doing my first steps in asp.net mvc trying to develop web api.
I have the following routing function:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "cdApiDefault",
url: "api/{controller}/{action}/{token}/{mid}/{id}",
defaults: new {
token = UrlParameter.Optional,
mid = UrlParameter.Optional,
id = RouteParameter.Optional }
);
}
and the following controller:
namespace cdapi.Controllers
{
public class PostsController : ApiController
{
// GET api/posts
public IEnumerable<string> Get()
{
return new string[] { "GET_value1", "GET_value2" };
}
// GET api/posts/5
public string Get(int id)
{
return "value!!!!!!!!!!!!!!!!!";
}
// POST api/posts
public void Post([FromBody]string value)
{
}
// PUT api/posts/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/posts/5
public void Delete(int id)
{
}
public String GetTest(String token, String mid)
{
return token + " - " + mid;
}
}
}
the following call
hxxp://localhost:52628/api/posts/5
(in my browser) yields some result, i.e., the function GET is being called and return a value.
However, when I try
hxxp://localhost:52628/api/posts/GetTest/MyTestToken/myTestMid
comes back with 'the resource can not be found' error message.
I thought that the {Action} should contain the function to call and that the 'token' and 'mid' should contain the values I specify. What do I do wrong?
ApiControllers work differently than regular MVC Controllers. Here, method names (GET, POST, PUT, DELETE) represent HTTP VERBS, not url fragment. In your first call,
/api/posts/5
this invokes Get(int).
To do routing like you want, switch to standard MVC by inheriting from System.Web.Mvc.Controller instead of System.Web.Http.ApiController and modify your methods to return ActionResult

Web Api GET method that has a nullable Guid possible?

I have a MVC Web API get method that I'd like to be able to pass a nullable Guid as a parameter. If I setup the GET with a "?Id=null" I get a 400 response. I can pass a empty guid but that I'd rather not do that.
No matter what I change the URI to, "id=, id=null etc" it won't accept null. Does anyone know how to make this work?
[HttpGet]
public User Get(Guid? Id)
Update Route config
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Full Http Get signature, sourceId is the param that id like to pass as null.
[HttpGet]
public IEnumerable<ActionItemsListViewModel> GetPagedList(int skip, int take, int page, int pageSize, [FromUri]List<GridSortInfo> sort, [FromUri] ActionItem.ActionItemStatusTypes? actionItemStatus, Guid? sourceId)
Found the problem, this filter was saying the ModelState was invalid.
public class ApiValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid )
{
var errors = actionContext.ModelState
.Where(e => e.Value.Errors.Count > 0)
.Select(e => e.Value.Errors.First().ErrorMessage).ToList();
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, string.Join(" ", errors));
}
}
}
Try to use:
[HttpGet]
public User Get(Guid? Id = null)
I was able to pass null to the Guid? when I use
query string parameter: api/values?id=null
route parameter: api/values/null
Controller:
public class ValuesController : ApiController
{
public User Get(Guid? Id)
{ ... }
}

MVC Web API, get sub items

I have a database with two tables. Countries and Cities where each city has a relation to a spesific country.
In my ASP.Net Web API I can get a list of countries by a GET request to http://example.com/api/countries to run the CountriesController. And I can get details about a country by http://example.com/api/countries/1.
If I want a list of all cities for a country the REST query URL should be http://example.com/api/countries/1/cities? And details for a City http://example.com/api/countries/1/cities/1
How can I accomplish this in ASP.Net Web API?
How about this, in global.asax.cs define an additional api route like so:
routes.MapHttpRoute(
name: "CityDetail",
routeTemplate: "api/countries/{countryid}/cities/{cityid}",
defaults: new { controller = "Cities" }
);
Then define a new CitiesController like so:
public class CitiesController : ApiController
{
// GET /api/values
public IEnumerable Get()
{
return new string[] { "value1", "value2" };
}
// GET /api/values/5
public string Get(int countryId, int cityid)
{
return "value";
}
// POST /api/values
public void Post(string value)
{
}
// PUT /api/values/5
public void Put(int countryId, int cityid, string value)
{
}
// DELETE /api/values/5
public void Delete(int countryId, int cityid)
{
}
}
Needless to say you might want to improve the controller implementation a bit :)

Routing to the actions with same names but different parameters

I have this set of routes:
routes.MapRoute(
"IssueType",
"issue/{type}",
new { controller = "Issue", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Here is the controller class:
public class IssueController : Controller
{
public ActionResult Index()
{
// todo: redirect to concrete type
return View();
}
public ActionResult Index(string type)
{
return View();
}
}
why, when i request http://host/issue i get The current request for action 'Index' on controller type 'IssueController' is ambiguous between the following action methods:
I expect that first one method should act when there is no parameters, and second one when some parameter specified.
where did i made mistake?
UPD: possible duplicate: Can you overload controller methods in ASP.NET MVC?
UPD 2: due to the link above - there is no any legal way to make action overloading, is it?
UPD 3: Action methods cannot be overloaded based on parameters (c) http://msdn.microsoft.com/en-us/library/system.web.mvc.controller%28VS.100%29.aspx
I would have one Index method that looks for a valid type variable
public class IssueController : Controller
{
public ActionResult Index(string type)
{
if(string.isNullOrEmpty(type)){
return View("viewWithOutType");}
else{
return View("viewWithType");}
}
}
EDIT:
How about creating a custom attribute that looks for a specific request value as in this post StackOverflow
[RequireRequestValue("someInt")]
public ActionResult MyMethod(int someInt) { /* ... */ }
[RequireRequestValue("someString")]
public ActionResult MyMethod(string someString) { /* ... */ }
public class RequireRequestValueAttribute : ActionMethodSelectorAttribute {
public RequireRequestValueAttribute(string valueName) {
ValueName = valueName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
return (controllerContext.HttpContext.Request[ValueName] != null);
}
public string ValueName { get; private set; }
}
I ran into a similar situation where I wanted my "Index" action to handle the rendering if I had an ID specified or not. The solution I came upon was to make the ID parameter to the Index method optional.
For example, I originally tried having both:
public ViewResult Index()
{
//...
}
// AND
public ViewResult Index(int entryId)
{
//...
}
and I just combined them and changed it to:
public ViewResult Index(int entryId = 0)
{
//...
}
You can do it using an ActionFilterAttribute that checks the parameters using reflection (I tried it) but it's a bad idea. Each distinct action should have its own name.
Why not just call your two methods "Index" and "Single", say, and live with the limitation on naming?
Unlike methods that are bound at compile time based on matching signatures, a missing route value at the end is treated like a null.
If you want the [hack] ActionFilterAttribute that matches parameters let me know and I'll post a link to it, but like I said, it's a bad idea.
All you have to do is mark your second Action with [HttpPost]. For instance:
public class IssueController : Controller
{
public ActionResult Index()
{
// todo: redirect to concrete type
return View();
}
[HttpPost]
public ActionResult Index(string type)
{
return View();
}
}

Resources