WebAPI 2.0 Multiple Get on single controller - asp.net-web-api

I'm currently trying to implement a simple WebAPI 2.0 controller to get and retrieve users from a central table.
Looking at implementing :
GetUserByName(string userName)
GetUserByID(int userId)
GetUserByEmail(string email)
Using Routing I have been able to get the api to work with GetById and GetByName. I have also added a route prefix to the controller level
The code looks like this so far, There isn't very much being done in the API controller at the moment I just wish to test that the correct methods are being hit.
[RoutePrefix("api/user")]
public class UserController : ApiController
{
[Route("")]
[HttpGet]
public IEnumerable<User> Get()
{
return new List<User>();
}
// GET: api/Users/5
[Route("{id:int}")]
public User Get(int id)
{
return new User();
}
[Route("{id}/PasswordHash")]
[HttpGet]
public string PasswordHash(int id)
{
return "test";
}
[Route(Name = "/{userName:alpha}")]
public User GetByName(string userName)
{
return new User();
}
[Route(Name = "/GetByEmail/{email}")]
[HttpGet]
public User GetByEmail(string email)
{
return new User()
}
// POST api/<controller>
[HttpPost]
[Route("")]
public string Post([FromBody]User value)
{
return "test";
}
}
Once I add in the get by email it doesn't seem to work, I've tried giving the method it's own custom routing but unfortunately it doesn't seem to work. Any suggestions would be great.

You have set the name of the routes not the routes themselves, and since both methods have the same signature with one string variable you get the problem, so change your code to be :
[Route("/{userName:alpha}")]
public User GetByName(string userName)
{
return new User();
}
[Route("/GetByEmail/{email}")]
[HttpGet]
public User GetByEmail(string email)
{
return new User()
}
hope this helps.

Related

ASP.NET Core WebAPI 404 error

I create a Web Api in asp.net core this the content of Api:
[Route("api/[controller]")]
public class BlogController : Controller
{
public IContext _context { get; set; }
public BlogController(IContext ctx)
{
_context = ctx;
}
[HttpGet]
[Route("api/Blog/GetAllBlog")]
public List<Blog> GetAllBlog()
{
return _context.Blogs.ToList();
}
}
as i know in ASp.net Core (WebApi Template) we don't need any configuration like registration Route, which we need in Asp.net Mvc 5.3 and older.
So when i try to call the GetAllBlog by browser or Postman, by this url http://localhost:14742/api/Blog/GetAllBlog , it gets me 404 error, what is problem?
You have already included the api/[controller] route at the top of the controller class so you don't need to include it again while defining route for accessing method.
In essence, change the Route to api/Blog/GetAllBlog to GetAllBlog. Your code should look like this:
[Route("api/[controller]")]
public class BlogController : Controller
{
public IContext _context { get; set; }
public BlogController(IContext ctx)
{
_context = ctx;
}
[HttpGet]
[Route("GetAllBlog")]
public List<Blog> GetAllBlog()
{
return _context.Blogs.ToList();
}
[HttpGet]
[Route("GetOldBlogs")]
public List<Blog> GetOldBlogs()
{
return _context.Blogs.Where(x => x.CreationDate <= DateTime.Now.AddYears(-2)).ToList();
}
}
You also need to have different route names for methods.
Hope this helps.

Access TempData in ExecuteResult Asp.Net MVC Core

I wanted to save notification in TempData and shown to user. I create extension methods for this and implement a class which Extends from ActionResult. I need to access TempData in override ExecuteResult method with ActionContext.
Extension Method:
public static IActionResult WithSuccess(this ActionResult result, string message)
{
return new AlertDecoratorResult(result, "alert-success", message);
}
Extends ActionResult class.
public class AlertDecoratorResult : ActionResult
{
public ActionResult InnerResult { get; set; }
public string AlertClass { get; set; }
public string Message { get; set; }
public AlertDecoratorResult(ActionResult innerResult, string alertClass, string message)
{
InnerResult = innerResult;
AlertClass = alertClass;
Message = message;
}
public override void ExecuteResult(ActionContext context)
{
ITempDataDictionary tempData = context.HttpContext.RequestServices.GetService(typeof(ITempDataDictionary)) as ITempDataDictionary;
var alerts = tempData.GetAlert();
alerts.Add(new Alert(AlertClass, Message));
InnerResult.ExecuteResult(context);
}
}
Call extension method from controller
return RedirectToAction("Index").WithSuccess("Category Created!");
I get 'TempData ' null , How can I access 'TempData' in 'ExecuteResult' method.
I was literally trying to do the exact same thing today (have we seen the same Pluralsight course? ;-) ) and your question led me to find how to access the TempData (thanks!).
When debugging I found that my override on ExecuteResult was never called, which led me to try the new async version instead. And that worked!
What you need to do is override ExecuteResultAsync instead:
public override async Task ExecuteResultAsync(ActionContext context)
{
ITempDataDictionaryFactory factory = context.HttpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory;
ITempDataDictionary tempData = factory.GetTempData(context.HttpContext);
var alerts = tempData.GetAlert();
alerts.Add(new Alert(AlertClass, Message));
await InnerResult.ExecuteResultAsync(context);
}
However, I have not fully understood why the async method is called as the controller is not async... Need to do some reading on that...
I find out the way to get the TempData. It need to get from ITempDataDictionaryFactory
var factory = context.HttpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory;
var tempData = factory.GetTempData(context.HttpContext);

How multiple Get function could be there in a web api controller

just see the scenario
public class CustomerController : ApiController
{
public IEnumerable<Customer> GetCustomersByID(int id)
{
}
public IEnumerable<Customer> GetCustomersByName(string name)
{
}
public IEnumerable<Customer> GetCustomersByEmail(string strEmail)
{
}
}
now tell me what i need to do as a result end user can call three get action by their name. how to handle this situation. thanks
You can set route for each method. Such as:
[Route("GetById/{id}")]
public IEnumerable<Customer> GetCustomersByID(int id)
{
}
You can call it getbyid/3. More details web api routing
Also there is a question for this issue.

UserManager in ApiController

In my project HttpContext is a member of Controller and I can use it in AccountController : Controller. But I can't access an information about current user in ApiController in contraction like
public class AccountController : ApiController
{
public UserManager<ApplicationUser> UserManager { get; private set; }
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.Current.GetOwinContext().Authentication;
}
}
}
So how to write custom ApiController right?
In the method below user variable shows me null on breakpoint. How can I retrive current user if I know that hi is logined?
public IHttpActionResult GetUser(int id)
{
var manager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var userid = User.Identity.GetUserId();
var user = manager.FindById(userid);
var data = new Person {Name = user.UserName, Age = 99};
return Ok(data);
}
From within any controller method you can do this.GetRequestContext().User to get the currently authenticated user. The static HttpContext.Current is not supported by WebApi.
manager.FindById(userid) retrieves a user from the database as opposed to the current . To get the current user, simply access the User property within your ApiController:
public class MyApiController : ApiController
{
IPrincipal GetCurrentUser(){
return User;
}
}
This may help you:
protected string UserId { get { return User.Identity.GetUserId(); } }

Put, Delete... Method not allowed in Orchard

I've created WebApi controller based on following tutorial: sebastienros website
My modules name is Company.Accounts.
public class AccountController : ApiController
{
[HttpPost]
public string LogIn([FromBody] UserModel user)
{
// this is working
return this.accountService.LogIn(user.UserName, user.Password);
}
[HttpPut]
public string SomePuthMethod([FromBody] UserModel user)
{
// method not allowed
// some code...
}
}
Implementation of IHttpRouteProvider looks like:
private IEnumerable<RouteDescriptor> GetAccountRoute()
{
yield return new HttpRouteDescriptor
{
Name = "Account",
Priority = 10,
RouteTemplate = "Api/Account",
Defaults = new
{
area = "Company.Accounts",
controller = "Account"
}
};
}
Unfortunately, everything except GET and POST *is not working*. I'm getting simple
Method not allowed.
What's wrong? My Orchard version is 1.7.1.
You put them in the MethodNames public HttpResponseMessage Post([FromBody]...){}

Resources