How to use asp.net web api different method in same controller? - asp.net-mvc

I want to use to asp.net web api different method in same api controller. I searched but I couldn't find.
For example:
public class HomeController : ApiController
{
AdFindDBEntities db = new AdFindDBEntities();
public HomeController()
{
db.Configuration.ProxyCreationEnabled = false;
}
[HttpGet]
public List<Ad> AllAds()
{
return db.Ad.ToList();
}
[HttpGet]
public IEnumerable<Ad> GetLastAds()
{
return db.Ad.OrderByDescending(x => x.CreatedDate).Take(20).ToList();
}
}
When I run the project AllAds method running. I don't know how use to GetLastAds method. Please help me!

Use [Route] attribute for separation call you actions
[HttpGet]
[Route("api/home/ads}")]
public List<Ad> AllAds()
{
...
}
[HttpGet]
[Route("api/home/ads/last}")]
public List<Ad> GetLastAds()
{
...
}

change the default route to have {action} in the route.
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
In that way you can call multiple actions by different urls.

Related

Pass Web API with different parameters to pass them to stored procedures

I have a Web API with about 6 stored procedures, each stored procedures has different parameter, for example 2 params or 3 params or 1 param and one stored procedures takes 0 param.
How can I pass those params to my web api?
This is my webConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
And my Controllers code:
public class channelsController : ApiController
{
[HttpGet]
[Route("api/channels/{code:string}/{search_by:string}")]
public IEnumerable<sp_get_channels_Result> Get(string code,string search)
{
myEntities db = new myEntities();
return db.sp_get_channels("", "all").AsEnumerable();
}
}
//no param
public class networksController : ApiController
{
[HttpGet]
public IEnumerable<sp_get_networks_Result> Get()
{
myEntities db = new myEntities();
return db.sp_get_networks().AsEnumerable();
}
}
But I get this error:
The inline constraint resolver of type DefaultInlineConstraintResolver was unable to resolve the following inline constraint: string.
can you try to change "search_by" into "search"
[HttpGet]
[Route("api/channels/{code}/{search}")]
public IEnumerable<sp_get_channels_Result> Get(string code,string search)
{
myEntities db = new myEntities();
return db.sp_get_channels("", "all").AsEnumerable();
}
:string
Is not a valid route constraint.
See the list of default constraints here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-constraints
You could write your own, but it's not there by default.

ASP.NET MVC - Attribute Routing not finding area view

I've been searching for answers for this everywhere, but I can't seem to find any. I basically have an MVC application setup and I am using the built in AttributeRouting for my routes.
The folder structure looks like this;
Models
Views
Controllers
Areas
Member
MemberAreaRegistration.cs
Controllers
HomeController.cs
Views
Home
Account.cshtml
And then I wire up my routes in the global.asax like this;
public class Application : System.Web.HttpApplication {
protected void Application_Start(){
AreaRegistration.RegisterAllAreas();
// other web optimization stuff
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
So then, MemberAreaRegistration.cs is simple.
namespace App.Web.Areas.Member {
public class MemberAreaRegistration: AreaRegistration {
public override string AreaName { get { return "Member"; } }
}
public override void RegisterArea( AreaRegistrationContext context){ }
}
And I try to wire it using the attributes...
/areas/member/controllers/homecontroller.cs
// ...
[Route("member/account")]
public ActionResult Account() { return View(); }
// ...
The problem is that this finds the route, but it cannot find the view. I get the following error;
The view 'Account' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
~/Views/Home/Account.aspx
~/Views/Home/Account.ascx
~/Views/Shared/Account.aspx
~/Views/Shared/Account.ascx
~/Views/Home/Account.cshtml
~/Views/Home/Account.vbhtml
~/Views/Shared/Account.cshtml
~/Views/Shared/Account.vbhtml
By all accounts, this should work fine - and if not, I expect the ~/area to at least be in the path it is trying to search. Do I have to wire something additional up to make this function?
I am using ASP.NET MVC 5.0
If I hardcode the absolute path of the view, it works. Obviously this is not a good situation though. I'd prefer it to find the view out of convention. But if I type return View("~/areas/member/views/home/account.cshtml"); I do get the view back - so I know it can access to file and that it is correct.
Here is my RouteConfig.cs per request
RouteConfig.cs
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes) {
// mvc attribute routing allows us to supersede normal routing mechanisms and
// declare our routes a bit more verbosely
routes.MapMvcAttributeRoutes();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "App.Web.Controllers" }
);
}
}
That's because, once you are defining your route as an action's attribute, ASP.NET MVC doesn't know which area it is in, hence it doesn't know where to look for Views.
In the Controller the Account action is in, try to explicitly specify a RouteArea attribute.
I'm writing this off the top of my head, but it should look like:
[RouteArea("Member")]
[RoutePrefix("member")]
public class HomeController: Controller {
[Route("account")]
public ActionResult Account() { return View(); }
}
or, alternatively:
[RouteArea("Member")]
public class HomeController: Controller {
[Route("member/account")]
public ActionResult Account() { return View(); }
}

Multi Tenant application using MapRoute

I have found a solution for implement multi-tenant in my asp.net mvc project and
I want know if it's correct or exist a better way.
I want organize more customers using the same application handling the web request, for example:
http://mysite/<customer>/home/index //home is controller and index the action
For this reason i changed the default maproute:
routes.MapRoute(
name: "Default",
url: "{customername}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
and I implemented a custom ActionFilterAttribute:
public class CheckCustomerNameFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting( ActionExecutingContext filterContext )
{
var customerName = filterContext.RouteData.Values["customername"];
var customerRepository = new CustomerRepository();
var customer = customerRepository.GetByName( customerName );
if( customer == null )
{
filterContext.Result = new ViewResult { ViewName = "Error" };
}
base.OnActionExecuting( filterContext );
}
}
and using it:
public class HomeController : Controller
{
[CheckCustomerNameFilterAttribute]
public ActionResult Index()
{
var customerName = RouteData.Values["customername"];
// show home page of customer with name == customerName
return View();
}
}
With this solution i can switch customer using customer name and correctly accept requests like this:
http://mysite/customer1
http://mysite/customer2/product/detail/2
...................................
This solution works well but I don't know if the best approach.
Does anyone know a better way?
You can model bind the customer name, and not have to pull it from route values:
public ActionResult Index(string customerName)
{
}

How to customize a URL to use a name different than my Controller?

I'm using ASP.NET MVC to develop a website and I need to customize my URL to use a name that is not the name of my Controller.
I want to use this Class/Method names:
public class CompanyController:Controller {
public ActionResult About() {
return View();
}
}
But I want to use the URL http://www.mysite.com/the-company/about-us to access my Controller/Method.
How should I proceed?
Thank you.
Since your question is mainly about controller naming I would (contrary to #Nissan Fan's answer) do at least this generalization, to make routing a bit more flexible and minimize the amount of routes, you'd have to define:
routes.MapRoute(
"CompanyRoute",
"the-company/{action}",
new { controller = "Company", action = "About" }
);
Your controller should of course be written this way:
public class CompanyController : Controller
{
[ActionName("about-us")]
public ActionResult About()
{
return View("About");
}
}
You will use URL Routing:
http://www.asp.net/learn/mvc/tutorial-05-cs.aspx
routes.MapRoute(
"AboutUs", // Route name
"the-company/about-us", // URL with parameters
new { controller = "CompanyController", action = "About" } // Parameter defaults
);

ASP.NET MVC Routing Question

I must be dense. After asking several questions on StackOverflow, I am still at a loss when it comes to grasping the new routing engine provided with ASP.NET MVC. I think I've narrowed down the problem to a very simple one, which, if solved, would probably allow me to solve the rest of my routing issues. So here it is:
How would you register a route to support a Twitter-like URL for user profiles?
www.twitter.com/username
Assume the need to also support:
the default {controller}/{action}/{id} route.
URLs like:
www.twitter.com/login
www.twitter.com/register
Is this possible?
What about
routes.MapRoute(
"Profiles",
"{userName}",
new { controller = "Profiles", action = "ShowUser" }
);
and then, in ProfilesController, there would be a function
public ActionResult ShowUser(string userName)
{
...
In the function, if no user with the specified userName is found, you should redirect to the default {controller}/{action}/{id} (here, it would be just {controller}) route.
Urls like www.twitter.com/login should be registered before that one.
routes.MapRoute(
"Login",
"Login",
new { controller = "Security", action = "Login" }
);
The important thing to understand is that the routes are matched in the order they are registered. So you would need to register the most specific route first, and the most general last, or all requests matching the general route would never reach the more specific route.
For your problem i would register routing rules for each of the special pages, like "register" and "login" before the username rule.
You could handle that in the home controller, but the controller method would not be very elegant. I'm guessing something like this might work (not tested):
routes.MapRoute(
"Root",
"{controller}/{view}",
new { controller = "Home", action = "Index", view = "" }
);
Then in your HomeController:
public ActionResult Index(string view) {
switch (view) {
case "":
return View();
case "register":
return View("Register");
default:
// load user profile view
}
}
OK I haven't ever properly tried this, but have you tried to extend the RouteBase class for dealing with users. The docs for RouteBase suggest that the method GetRouteData should return null if it doesn't match the current request. You could use this to check that the request matches one of the usernames you have.
You can add a RouteBase subclass using:
routes.Add(new UserRouteBase());
When you register the routes.
Might be worth investigating.
i think your question is similar to mine. ASP.NET MVC Routing
this is what robert harvey answered.
routes.MapRoute( _
"SearchRoute", _
"{id}", _
New With {.controller = "User", .action = "Profile", .id = ""} _
)
Here is an alternative way to standar route registration:
1. Download RiaLibrary.Web.dll and reference it in your ASP.NET MVC website project
2. Decoreate controller methods with the [Url] Attributes:
public SiteController : Controller
{
[Url("")]
public ActionResult Home()
{
return View();
}
[Url("about")]
public ActionResult AboutUs()
{
return View();
}
[Url("store/{?category}")]
public ActionResult Products(string category = null)
{
return View();
}
}
BTW, '?' sign in '{?category}' parameter means that it's optional. You won't need to specify this explicitly in route defaults, which is equals to this:
routes.MapRoute("Store", "store/{category}",
new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3. Update Global.asax.cs file
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoutes(); // This do the trick
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
How to set defaults and constraints? Example:
public SiteController : Controller
{
[Url("admin/articles/edit/{id}", Constraints = #"id=\d+")]
public ActionResult ArticlesEdit(int id)
{
return View();
}
[Url("articles/{category}/{date}_{title}", Constraints =
"date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")]
public ActionResult Article(string category, DateTime date, string title)
{
return View();
}
}
How to set ordering? Example:
[Url("forums/{?category}", Order = 2)]
public ActionResult Threads(string category)
{
return View();
}
[Url("forums/new", Order = 1)]
public ActionResult NewThread()
{
return View();
}

Resources