I am following msdn tutorials to create a project that has 2 controllers with various routing and http webapi variations. .Net Framework 4.5.2
IDS: VS Community 2017
I have 2 custom controllers: Products controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using product_search_web_app.Models;
namespace product_search_web_app.Controllers
{
//[RoutePrefix("api/Products")]
public class ProductsController : ApiController
{
private product_search_web_appContext db = new product_search_web_appContext();
// GET: api/PSProducts
[Route("")]
[HttpGet]
public IQueryable<PSProduct> GetPSProducts()
{
return db.PSProducts;
}
// GET: api/PSProducts/5
[Route("{id}")]
[HttpGet]
[ResponseType(typeof(PSProduct))]
public async Task<IHttpActionResult> GetPSProduct(Guid id)
{
PSProduct pSProduct = await db.PSProducts.FindAsync(id);
if (pSProduct == null)
{
return NotFound();
}
return Ok(pSProduct);
}
}
}
and ProductSearch Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using product_search_web_app.Models;
namespace product_search_web_app.Controllers
{
public class ProductSearchController : ApiController
{
PSSellerProduct[] SellerProducts = new PSSellerProduct[] {
// Initializations
};
// GET api/<controller>
//[Route("api/ProductSearch")]
//[HttpGet]
public IEnumerable<PSSellerProduct> GetAllProducts()
{
return SellerProducts;
}
[Route("api/ProductSearch/Products/{PSProductId}")]
public IHttpActionResult GetProductById(string PSProductID)
{
var Product = SellerProducts.FirstOrDefault((sp) => sp.ProductId.ToString() == PSProductID);
if (Product != null)
return Ok(Product);
else return NotFound();
}
[Route("api/ProductSearch/Sellers/{SellerId}/Products/{ProductId?}")]
public IHttpActionResult GetProductsBySeller([FromUri(Name = "SellerId")]string SellerId, [FromUri(Name = "ProductId")]string ProductId = "")
{
if (String.IsNullOrEmpty(ProductId))
{
var Products = SellerProducts.Where((sp) => sp.SellerID.ToString() == SellerId);
if (Products != null)
return Ok(Products);
else return NotFound();
}
else
{
var Product = SellerProducts.FirstOrDefault((sp) => sp.SellerID.ToString() == SellerId && sp.ProductId.ToString() == ProductId);
if (Product != null)
return Ok(Product);
else return NotFound();
}
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
I created the controllers following msdn instructions. The ProductSearch was created as empty controller, Products created following https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/create-a-rest-api-with-attribute-routing
I am trying and failing to achieve the falling goals: 1. Call /api/Products to return a a list of products backed by GetPSPRoducts method. Instead, the browser ends up loading the "Home" version of web page (the default view controller). 2. Call api/ProductSearch to return all product. Right now it returns 404 version. If I call api/ProductSearch/GetAllProducts, then is returns all products, but that is not what i want. Note that api/ProductSearch/Products/ or api/ProductSearch/Seller//Products is working fine.
These are the configs in RouteConfig.cs:
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace product_search_web_app
{
public class RouteConfig
{
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 WebApiConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace product_search_web_app
{
public static class WebApiConfig
{
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.Routes.MapHttpRoute(
// name: "ActionApi",
// routeTemplate: "api/{controller}/{action}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
}
}
}
and Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace product_search_web_app
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
All help appreciated! Update: If I set ProductsController in the following way, both "/api/Products/" and "http://localhost:59411/" are getting mapped to Products Controller. I would have expected that the latter would go to the default Home view.
//[RoutePrefix("api/Products")] -->Intentionally commented
public class ProductsController : ApiController
{
private product_search_web_appContext db = new product_search_web_appContext();
// GET: api/PSProducts
//If I replace route below to api/Products, it defaults the requests back to Home View
[Route("")]
[HttpGet]
public IQueryable<PSProduct> GetPSProducts()
{
return db.PSProducts;
}