It`s possible to create a GET action based on multiple id's inputted?
For example how can I change this method to be GetCustomer([FromRoute] int id, int code_id)?
// GET: api/Customer/5
[HttpGet("{id}")]
public async Task<IActionResult> GetCustomer([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var customerMaster = await _context.CustomerMaster.SingleOrDefaultAsync(m => m.Code == id);
if (customerMaster == null)
{
return NotFound();
}
return Ok(customerMaster);
}
Use AttributeRouting:
// GET: api/Customer/5/3
[Route("api/Customer/{id}/{code_id}")]
public async Task<IActionResult> GetCustomer(int id, int code_id)
{
...
return Ok(customer);
}
Related
i have an action inside of users and i want that action to return the user to another action in another controller but not in the router parameter, Here is a sample
public IActionResult LoginCheck(UserForm user)
{
AuthUser auth = new AuthUser(_context);
var result = auth.IsLoggedIn(user.Email, user.Password);
if(result.isfound==false)
{
return NotFound();
}
result.User.IsAuth = true;
return RedirectToAction("Home","Index",result.User);
}
public async Task<IActionResult> Index(User user)
{
if(user.IsAuth == false)
{
return Unauthorized();
}
just part of the code
Home index did not use the incoming user as it was sent as router parameters i think
Welcome to stackoverflow!
You can use TempData to achieve that.
public IActionResult LoginCheck(UserForm user)
{
AuthUser auth = new AuthUser(_context);
var result = auth.IsLoggedIn(user.Email, user.Password);
if(result.isfound==false)
{
return NotFound();
}
result.User.IsAuth = true;
TempData["user"] = result.User;
return RedirectToAction("Home","Index");
}
Then you can get it in the other action
public async Task<IActionResult> Index()
{
if(TempData["user"] == null)
{
return Unauthorized();
}else{
var someUser= (User)TempData["user"];
}
}
But I do not recommend using TempData for sensitive data.
You can use second action as method:
public async Task<IActionResult> LoginCheck(UserForm user)
{
AuthUser auth = new AuthUser(_context);
var result = auth.IsLoggedIn(user.Email, user.Password);
if(result.isfound==false)
{
return NotFound();
}
result.User.IsAuth = true;
return await Index(result.User);
}
second action
[NonAction] // Indicates that a controller method is not an action method.
public async Task<IActionResult> Index(User user)
{
if(user == null)
{
return Unauthorized();
}
else{
var someUser= user;
}
}
Use redirection make browser to handle this transfer and it is slower.
I have a post method to add a new category and save it to the database. and I want to return CreateAtAction to another getmethod.but as I execute the code the data saves in the database with 200 success.
When I try to use Swagger UI though I get "Can not parse json data" and this post method does not move to another get method.
CategoryController.cs
[HttpPost]
public async Task<IActionResult> AddCategory([FromBody] Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_categoryRepository.Add(category);
await Task.Run(() => _categoryRepository.SaveChanges());
return CreatedAtAction(nameof(GetCategoryById) , new { id = category.Id }, category);
}
[HttpGet("{id}")]
public IActionResult GetCategoryById([FromRoute]long id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//var category = await _context.Category.FirstOrDefaultAsync(i => i.ParentId == id);
var ListCategories = _categoryRepository.GetById(id);
if (ListCategories == null)
{
return NotFound();
}
return Ok(ListCategories);
}
I come from EF 6 where inserting a child object into a parent entity's list would look something like this:
[HttpPost, Route("{id:int}")]
public async Task<IActionResult> Post(int id, MenuViewModel menu){
if (!ModelState.IsValid)
return BadRequest("Something is wrong with the model");
var restaurant = await db.Restaurants.Where(r => r.Id == id).Include(r=> r.Menus).FirstOrDefaultAsync();
if (restaurant == null)
return BadRequest("That restaurant does not exist");
var menuModel = Mapper.Map<Menu>(menu);
restaurant.Menus.Add(menuModel);
db.Restaurants.Update(restaurant);
await db.SaveChangesAsync();
return Ok(Mapper.Map<MenuViewModel>(menuModel));
}
Try add your child to db then save its should be work
[HttpPost, Route("{id:int}")]
public async Task<IActionResult> Post(int id, MenuViewModel menu){
if (!ModelState.IsValid)
return BadRequest("Something is wrong with the model");
var restaurant = await db.Restaurants.Where(r => r.Id == id).Include(r=> r.Menus).FirstOrDefaultAsync();
if (restaurant == null)
return BadRequest("That restaurant does not exist");
var menuModel = Mapper.Map<Menu>(menu);
restaurant.Menus.Add(menuModel);
db.Menus.Add(menuModel); //Add to DBContext
db.Restaurants.Update(restaurant);
await db.SaveChangesAsync();
return Ok(Mapper.Map<MenuViewModel>(menuModel));
}
Hi I have an OData API that I'm trying to run locally but whenever it is being run I cannot load any of the resources. When I run the API, I get this screen with the information on the entities.
enter image description here
Whenever I try to navigate to one using a URL such as http://localhost:51578/Managers, I get an error saying No HTTP resource was found that matches the request URI 'http://localhost:51578/Managers'. Here is the code I have for the Manager Controller.
public class ManagerController : ODataController
{
DatabaseContext db = new DatabaseContext();
private bool ManagerExists(Guid key)
{
return db.Managers.Any(p => p.Id == key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
[EnableQuery]
public SingleResult<Manager> Get([FromODataUri] Guid key)
{
IQueryable<Manager> result = db.Managers.Where(p => p.Id == key);
return SingleResult.Create(result);
}
[HttpPost]
public async Task<IHttpActionResult> Post(Manager manager)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Managers.Add(manager);
await db.SaveChangesAsync();
return Created(manager);
}
[HttpPatch]
public async Task<IHttpActionResult> Patch([FromODataUri] Guid key, Delta<Manager> manager)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.Managers.FindAsync(key);
if (entity == null)
{
return NotFound();
}
manager.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ManagerExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
[HttpPut]
public async Task<IHttpActionResult> Put([FromODataUri] Guid key, Manager update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (key != update.Id)
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ManagerExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
[HttpDelete]
public async Task<IHttpActionResult> Delete([FromODataUri] Guid key)
{
var manager = await db.Managers.FindAsync(key);
if (manager == null)
{
return NotFound();
}
db.Managers.Remove(manager);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
}
Make sure that your WebApiConfig.cs file has the following:
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel(),
defaultHandler: HttpClientFactory.CreatePipeline(innerHandler: new HttpControllerDispatcher(config),
handlers: new[] { new ODataNullValueMessageHandler() }));
This will allow your route to be http://localhost:51578/Managers since we set "routePrefix" to null. If route prefix had something else like "v4" your url would look like http://localhost:51578/v4/Managers.
I have a controller like this
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int id)
{
//Code code
foo(id); // Foo accept Int or Null
}
This do work, if call api/Foo/MyController/1, but i needed call api/Foo/MyController like it "GetAll" the parameter id now is null and the stuff into controller return all, how go there?
You can add a new method and route:
[Route("api/Foo/MyController")]
public IHttpActionResult Get()
{
//Code code
}
Edit: to reuse the same method you could use optional parameters:
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int? id)
{
if (id.HasValue)
{
// get by id
}
else
{
// get all
}
}
Why don't have 2 separate methods:
[Route("api/Foo/")]
public IHttpActionResult GetAll()
{
// code
}
[Route("api/Foo/{id}")]
public IHttpActionResult GetById(int id)
{
// code
}
For clarity (readability, maintainability, supportability).
You could do also a optional parameter:
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int? id = null)
{
IQueryable foo = GetData();
if (id.HasValue)
{
foo = foo.Where(e => e.Id == id.Value);
}
//...
}