Using Action link with Web Api Controller - asp.net-web-api

How can I use ActionLink when calling an action on a controller that is a WebApi controller.
public class RequestController : ApiController
{
[ActionName("CreateAction")]
[ResponseType(typeof(Request))]
public async Task<IHttpActionResult> PostRequest(Request request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Requests.Add(request);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = request.Id }, request);
}
}
in my layout page can I do this
#Html.ActionLink("Request", "CreateAction", "api/Request", new { area = "" }, null)
Jawahar

You can generate a link to an API controller using the standard Url helper property. The following link will point to an Albums controller and pass along an id parameter with a value of 3:
#Url.RouteUrl("DefaultApi", new { httproute=true, controller="Albums", id=3})
Please refer to this link
http://odetocode.com/blogs/scott/archive/2013/03/27/webapi-tip-5-generating-links.aspx

Related

User optional Attribute Route to indicate tenant in dotnet core web api

Is there a way to define optional route parameter for a REST dotnet core webapi project?
I'd like to define an optional tenant parameter within my API controller. If the parameter is present, I'd like to use it to filter my queries.
api.example.com/tenant1/users -> all users of tenant1
api.example.com/users -> all users in the system
[Route ("{tenant:guid?}/[controller]")]
public class UsersController {
// GET api.example.com/{tenant}/users
[HttpGet]
public async Task<IActionResult> GetUsers (Guid tenant) {
...
if(tentant != null){
var users = await _db.Users.GetAllByTentant(tenant);
return Ok (users);
} else {
var users = await _db.Users.GetAll();
return Ok (users);
}
}
}
Tanks to the hint of Yuli
[Route ("[controller]")]
public class UsersController {
// GET api.example.com/users
[HttpGet]
public async Task<IActionResult> GetUsers () {
...
var users = await _db.Users.GetAll();
return Ok (users);
}
// GET api.example.com/{tenant}/users
[HttpGet("/{tenant}/[controller]")]
public async Task<IActionResult> GetUsers (Guid tenant) {
...
var users = await _db.Users.GetAllByTentant(tenant);
return Ok (users);
}
}

Access claims in web api controller in mvc5 project

I have a MVC5 project with ASP.NET Identity. I'm using Claims in my MVC5 controllers like below.
public ActionResult Index()
{
var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
var email = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Email).Select(c => c.Value).SingleOrDefault();
}
However the Claims are not available in a WebApi controller in the same project. What do I have to do to get access to the Claims of the logged in user in a WebApi Controller in a MVC5 project?
Thank You.
Make sure your WebAPI controller or action is decorated with [Authorize]. You will never get current user context for anonymous requests.
[HttpGet]
[Authorize]
public IHttpActionResult Get()
{
try
{
var user = this.User as ClaimsPrincipal; //OR
var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
var email = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Email).Select(c => c.Value).SingleOrDefault();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
return Ok();
}

How to use ASP.Net 5 CreatedAtAction

I'm trying to do an HttpPost to create an entity and I want to return a 201 created with the location header set to https://mysite/api/entity/1. I can't figure out how to do this while returning an IActionResult.
Calling it like this
return CreatedAtAction("Get", new { id = entity.Id }, "/{id}");
I get https://mysite/api/entity?id=11
I can't figure out how to get what I want.
I assign a route name to the Get action and reference it by name to make this work. For example:
// GET api/values/5
[HttpGet("{id}", Name="GetAction")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public IActionResult Post([FromBody]string value)
{
return this.CreatedAtRoute(
"GetAction", new { id = 5 }, new { id = 5 });
}

Post Scalar data type using HttpClient.PostAsJsonAsync

I am invoking ASP .Net Web API using HttpClient and invoke actions successfully. Also I am able to POST custom object into action as well.
Now problem I am facing is, not able to post scalar data type like Integer,String etc...
Below is my controller and application code that invokes action
// Test application that invoke
[Test]
public void RemoveCategory()
{
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = client.PostAsJsonAsync<string>("http://localhost:49931/api/Supplier/RemoveCategory/", "9").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
// Controller and Action in Web API
public class SupplierController : ApiController
{
NorthwindEntities context = new NorthwindEntities();
[HttpPost]
public HttpResponseMessage RemoveCategory(string CategoryID)
{
try
{
int CatId= Convert.ToInt32(CategoryID);
var category = context.Categories.Where(c => c.CategoryID == CatId).FirstOrDefault();
if (category != null)
{
context.Categories.DeleteObject(category);
context.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, "Delete successfully CategoryID = " + CategoryID);
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Invalid CategoryID");
}
}
catch (Exception _Exception)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, _Exception.Message);
}
}
When I Post custome object that represent "Category" table in Northwind database all things working properly but I am not able to post scalar data like Integer and String
When I am post string data type I am getting following exception
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:49931/api/Supplier/RemoveCategory/'.","MessageDetail":"No action was found on the controller 'Supplier' that matches the request."}
Can anyone guide me?
You will have to mark your CategoryID parameter as [FromBody]:
[HttpPost]
public HttpResponseMessage RemoveCategory([FromBody] string CategoryID)
{ ... }
By default, simple types such as string will be model bound from the URI.

Migrate custom route to ASP.NET MVC custom route to support List<string>

I have a URL in a Django based web app that looks similar to this:
/market/prices/2011-05-01/min/stocks/msft/dell/appl/
The application is being rewritten in ASP.NET MVC 3. I need to maintain the URL.
The crux of the problem is that I to support the multiple stock ticker symbols separated by forward slashes.
I want a custom route that looks like this:
routes.MapRoute(
"Stocks",
"{queryDate}/{minOrMax}/stocks/{listOfStocksSeparatedByForwardSlash}",
new { controller = "Market", action = "Prices" }
);
The controller would look something like:
public ActionResult Prices(string queryDate, string minOrMax, ICollection<string> listOfStocksSeparatedByForwardSlash) {
var model = repository.List(queryDate, minOrMax, listOfStocksSeparatedByForwardSlash);
return View(model );
}
My current solution is as follows:
routes.MapRoute(
"Stocks",
"{queryDate}/{minOrMax}/stocks/{*listOfStocksSeparatedByForwardSlash}",
new { controller = "Market", action = "Prices" }
);
public ActionResult Prices(string queryDate, string minOrMax, string listOfStocksSeparatedByForwardSlash) {
var list = listOfStocksSeparatedByForwardSlash.Split('/').ToList();
var model = repository.List(queryDate, minOrMax, list);
return View(model );
}
Although this works, I'm interested to know if there is a better way to do this?
Okay, this is an option, although I think your approach is easier.
You can provide a RouteHandler attached to a route, like so:
routes.MapRoute(
name: "Test",
url: "Test/{someDate}/{*tickerSymbols}",
defaults: new { controller = "Home", action = "Test" }).RouteHandler = new SlashSeparatedTrailingParametersRouteHandler("tickerSymbols", "tickers");
with the route handler being
public class SlashSeparatedTrailingParametersRouteHandler : IRouteHandler
{
private readonly string catchallParameterName;
private readonly string actionTargetParameter;
public SlashSeparatedTrailingParametersRouteHandler(string catchallParameterName, string actionTargetParameter)
{
this.catchallParameterName = catchallParameterName;
this.actionTargetParameter = actionTargetParameter;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
IRouteHandler handler = new MvcRouteHandler();
var vals = requestContext.RouteData.Values;
vals[this.actionTargetParameter] = vals[this.catchallParameterName].ToString().Split('/');
return handler.GetHttpHandler(requestContext);
}
}
If this is your controller action:
[HttpGet]
public ActionResult Test(DateTime someDate, string[] tickers)
{
if (tickers == null)
{
throw new ArgumentNullException("tickers");
}
return Content(string.Format("{0} and {1}", someDate, tickers.Length.ToString(CultureInfo.InvariantCulture)));
}
and this your post:
http://localhost/Test/12-06-2012/Foo/Bar
then your output is:
12/6/2012 12:00:00 AM and 2
On the elegance this this improves the parameter on the action method at the expense of having to write your own route handler.

Resources