When send Parameter pagenumber to web api by post man action not working or recognize? - asp.net-core

I work on .net core 6 web api I face issue when
send paramter pagenumber on url by post man
action not catched by break point debug .
so what is issue and How to solve It ?
i try with url
https://localhost:7235/api/items/pageNumber=1
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
it return error 200 bad Request .
but i try with url below
https://localhost:7235/api/items/
[HttpGet]
[Route("")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
it working hit controller success and return data success fromitems controller action get all .
so What is issue please and How to solve it ?
Updated post not working
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
for this action you need to use this url:
https://localhost:7235/api/items/1
not working and it give me error 500 internal server error
all controller items
using DomainModel.Entities;
using DomainModel.Pagination;
using DomainModel.ViewModel;
using k8s.Models;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Service.Contract;
using Service.Features.CustomerFeatures.Commands;
using Service.Features.CustomerFeatures.Queries;
namespace WebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ItemsController : Controller
{
private readonly IitemService _iitem;
private readonly IPageHelper<ItemsViewModel> _pageHelper;
public ItemsController(IitemService iitem, IPageHelper<ItemsViewModel> pageHelper)
{
_iitem = iitem;
_pageHelper = pageHelper;
}
[HttpPost]
public async Task<IActionResult> Create(Items item)
{
await _iitem.AddAsync(item);
return Ok();
}
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
var allitems = _iitem.GetAllItems();
var result = _pageHelper.GetPage(allitems.AsQueryable(), pageNumber);
var itemsdata = new ItemsPageViewModel
{
items = result.Items,
Pager = result.Pager
};
return Ok(itemsdata);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var details = await _iitem.GetByIdAsync(id);
return Ok(details);
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await _iitem.DeleteAsync(id);
return Ok();
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, Items item)
{
if (id != item.Id)
{
return BadRequest();
}
await _iitem.UpdateAsync(id, item);
return Ok();
}
}
}

The error you are actually getting is
AmbiguousMatchException: The request matched multiple endpoints.
This is because you have two actions that have the same route:
// for this action you need to use this url:
// https://localhost:7235/api/items/1
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
var allitems = _iitem.GetAllItems();
var result = _pageHelper.GetPage(allitems.AsQueryable(), pageNumber);
var itemsdata = new ItemsPageViewModel
{
items = result.Items,
Pager = result.Pager
};
return Ok(itemsdata);
}
// for this action you ALSO need to use this url:
// https://localhost:7235/api/items/1
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var details = await _iitem.GetByIdAsync(id);
return Ok(details);
}
Both actions are HttpGet and both use the same route:
https://localhost:7235/api/items/x
you need to change the route for one of them.
Routing to controller actions in ASP.NET Core

Related

DotNet - API - Can't access endpoint

I am passing through quite a similar challenge to the one reported on this post - .Net Core API Endpoint not allowing QueryString parameters - but the accepted answer hasn't worked for me, so I am seeking some guidance.
[HttpGet, Route("api/indicators/getindicatorsvalues/{companyId=companyId}/{pathToFile=pathToFile}")]
[ProducesResponseType(typeof(ComputedIndicatorVM), StatusCodes.Status200OK)]
public async Task<IActionResult> GetIndicatorsValues([FromQuery] Guid companyId, [FromQuery] string pathToFile)
{
//code goes here
}
[HttpGet("{id}")]
[ProducesResponseType(typeof(IndicatorDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetByIdAsync(Guid id)
{
//some more code goes here
}
Calling the 1st endpoint:
URL: https://localhost:5001/api/indicators/GetIndicatorsValues?companyId=cTest&pathToFile=ptfTest
Result: {"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"|6c8dcccd-412c0e1f0b9eb222.","errors":{"id":["The value 'GetIndicatorsValues' is not valid."]}}
Calling the 2nd endpoint works just fine:
URL: https://localhost:5001/api/indicators/DFAF6EAE-AB4B-4563-B37E-57DEF730A1D7
It seems by the response of the first endpoint that it is considering GetIndicatorsValues as a param for the second endpoint?
Or am I missing something else?
According to your description, it seems this issue is the https://localhost:5001/api/indicators/GetIndicatorsValues will match both the GetIndicatorsValues and GetByIdAsync. I guess your has a default rule which is like {controller}/{action}/{id?}.
I suggest you could try to modify the controller codes to avoid match the same method and then it will work well.
[HttpGet, Route("api/indicators/getindicatorsvalues/{companyId=companyId}/{pathToFile=pathToFile}")]
[ProducesResponseType(typeof(ComputedIndicatorVM), StatusCodes.Status200OK)]
public async Task<IActionResult> GetIndicatorsValues([FromQuery] Guid companyId, [FromQuery] string pathToFile)
{
//code goes here
}
[HttpGet("api/indicators/getindicatorsvalues/GetByIdAsync/{id}")]
[ProducesResponseType(typeof(IndicatorDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetByIdAsync(Guid id)
{
//some more code goes here
}
Sorted:
[HttpGet]
[ProducesResponseType(typeof(IndicatorDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetByIdAsync(Guid id)
{
var indicator = await this.indicatorsService.GetByIdAsync(id);
if (indicator == null)
{
return NotFound();
}
return Ok(indicator);
}
[HttpGet("GetIndicatorsValues")]
[ProducesResponseType(typeof(ComputedIndicatorVM), StatusCodes.Status200OK)]
public async Task<IActionResult> GetIndicatorsValues([FromQuery] Guid companyId, [FromQuery] string pathToFile)
{
try
{
if (companyId!=default && !string.IsNullOrEmpty(pathToFile))
{
List<ComputedIndicatorVM> computedIndicatorsViewModel = new List<ComputedIndicatorVM>();
List<ComputedIndicatorDto> dtoList = await this.indicatorsService.CalculateIndicators(companyId, pathToFile);
computedIndicatorsViewModel = this.mapper.Map<List<ComputedIndicatorVM>>(dtoList);
return Ok(computedIndicatorsViewModel);
}
else
{
return NotFound();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
throw ex;
}
}

add update and delete product methods not working in postman and not making any change in my database

services.AddAuthorization(options =>
{
options.AddPolicy("RequireLoggedIn", policy => policy.RequireRole("Admin", "Customer", "Moderator").RequireAuthenticatedUser());
options.AddPolicy("RequireAdministratorRole", policy => policy.RequireRole("Admin").RequireAuthenticatedUser());
});
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NG_Core_Auth.Data;
using NG_Core_Auth.Models;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace NG_Core_Auth.Controllers
{
[Route("api/[controller]")]
public class ProductController : Controller
{
private readonly ApplicationDbContext _db;
public ProductController(ApplicationDbContext db)
{
_db = db;
}
// GET: api/values
[HttpGet("[action]")]
[Authorize(Policy = "RequireLoggedIn")]
public IActionResult GetProducts()
{
return Ok(_db.Products.ToList());
}
[HttpPost("[action]")]
[Authorize(Policy = "RequireAdministratorRole")]
public async Task<IActionResult> AddProduct([FromBody] ProductModel formdata)
{
var newproduct = new ProductModel
{
Name = formdata.Name,
ImageUrl = formdata.ImageUrl,
Description = formdata.Description,
OutOfStock = formdata.OutOfStock,
Price = formdata.Price
};
await _db.Products.AddAsync(newproduct);
await _db.SaveChangesAsync();
return Ok(new JsonResult("The Product was Added Successfully"));
}
[HttpPut("[action]/{id}")]
[Authorize(Policy = "RequireAdministratorRole")]
public async Task<IActionResult> UpdateProduct([FromRoute] int id, [FromBody] ProductModel formdata)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var findProduct = _db.Products.FirstOrDefault(p => p.ProductId == id);
if (findProduct == null)
{
return NotFound();
}
// If the product was found
findProduct.Name = formdata.Name;
findProduct.Description = formdata.Description;
findProduct.ImageUrl = formdata.ImageUrl;
findProduct.OutOfStock = formdata.OutOfStock;
findProduct.Price = formdata.Price;
_db.Entry(findProduct).State = EntityState.Modified;
await _db.SaveChangesAsync();
return Ok(new JsonResult("The Product with id " + id + " is updated"));
}
[HttpDelete("[action]/{id}")]
[Authorize(Policy = "RequireAdministratorRole")]
public async Task<IActionResult> DeleteProduct([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// find the product
var findProduct = await _db.Products.FindAsync(id);
if (findProduct == null)
{
return NotFound();
}
_db.Products.Remove(findProduct);
await _db.SaveChangesAsync();
// Finally return the result to client
return Ok(new JsonResult("The Product with id " + id + " is Deleted."));
}
}
}
I work the controller with add update and delete methods I run the application and it run successfully with https://localhost:44301/ url then I make all the steps correctly in postman by adding https://localhost:44301/api/product/addproduct, putting headers and put the data I want to insert it in the body row and use post method I click send it return 401 Unauthorized, what is the problem ?
Iposted Productcontroller.cs and part of startup.cs files
Try to do a POST in Postman to your Login endpoint first. This will give the cookie to Postman that you are logged in (and what roles you have). Then next you should be able to POST successfully to your endpoints with Authorize attributes

Sent value from an action to another action

How to pass the parameter from the first method to the second?
I want to use id in public async Task<IActionResult> CreateReport.
public IActionResult CreateReport(int id)
{
return View();
}
// POST: MemeReports/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateReport([Bind("Id_report,Id_user,Id_meme,Description")] MemeReports memeReports)
{
memeReports.id_meme=id //i want do this
if (ModelState.IsValid)
{
db.Add(memeReports);
await db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(memeReports);
}
Simply pass it in your post method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateReport(int id, [Bind("Id_report,Id_user,Id_meme,Description")] MemeReports memeReports)
{
memeReports.id_meme=id //i want do this
if (ModelState.IsValid)
{
db.Add(memeReports);
await db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(memeReports);
}
Your first method gets called if the site yourdomain/createreport/1 (or yourdomain/createreport?id=1) is called and shows the createReport View.
If you submit a post from that page you will post the id, too.
You can use TempData which stores data until it's read :
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.1#tempdata
In ConfigureServices function :
services.Configure<CookieTempDataProviderOptions>(options =>
{
options.Cookie.IsEssential = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddSessionStateTempDataProvider();
services.AddSession();
In Configure function :
app.UseCookiePolicy();
app.UseSession();
Then in CreateReport function :
public IActionResult CreateReport(int id)
{
TempData["id"] = 1;
return View();
}
You can read this value in post function :
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateReport([Bind("Id_report,Id_user,Id_meme,Description")] MemeReports memeReports)
{
var value = TempData != null ? (TempData["id"]?.ToString() ?? "No TempData Value") : "No TempData";
memeReports.id_meme= value;
if (ModelState.IsValid)
{
db.Add(memeReports);
await db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(memeReports);
}
TempData should work after the user accepts the cookie policy on the site.

.Net Core 2.0 Web API controller not working and getting 404

I have something very very strange. I have 2 controllers. UploadController and AccountController. Theye were both working, and now when I try the AccountController it give error 404. ik don't get it.
This is how my AccountController looks like:
namespace CoreAngular.Controllers
{
//[Authorize]
[Produces("application/json")]
[Route("api/account")]
public class AccountController : Controller
{
private IRepository repository;
public AccountController(IDatabaseClient<DocumentClient> client)
: this ( new UserRepository(client))
{
}
public AccountController(IRepository repository)
{
this.repository = repository;
}
[HttpGet]
public async Task<ActionResult> Get(string id)
{
var start = DateTime.Now.TimeOfDay;
if (string.IsNullOrEmpty(id))
{
return BadRequest();
}
var user = await repository.GetAsync(id);
if (user == null)
{
return NotFound();
}
var userDTO = new UserGetDTO()
{
image = Convert.ToBase64String(user.image.image),
id = user.id,
time = DateTime.Now.Subtract(start).Millisecond
};
return Ok(userDTO);
}......
Do I miss something here? I know I comentet out the [Authorize], but i just wanted to try to connect.
You should specify route template in HttpGet attribute:
[HttpGet("{id}")]
public async Task<ActionResult> Get(string id)
{
// ...
}

WebApi for Email delivery

I created a Web API controller inside my ASP.NET MVC 4 Website to specifically send emails so that I can consume it for this purpose and eventually provide it to other consumers (Mobile, etc).
Everything is working fine but I want to use it asynchronously, altough it's not working that way, my website blocks until the work is finished.
I have a regular Controller where I call a helper class that calls the API.
Controller Code :
[HttpPost]
public async Task<ActionResult> ContactUs(ContactUsModel model)
{
ExternalApiCalls extApi = new ExternalApiCalls();
await extApi.PostContactUs(model).ConfigureAwait(false);
return RedirectToAction("ContactUsSuccess", "Account");
}
Helper Class Code :
public class ExternalApiCalls
{
public HttpClient client { get; set; }
public ExternalApiCalls()
{
client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:10239/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task PostContactUs(ContactUsModel model)
{
try
{
var response = await client.PostAsJsonAsync("api/WAPIMail", model).ConfigureAwait(false);
}
catch (HttpRequestException ex)
{
}
catch (System.FormatException)
{
}
finally
{
}
}
}
Web API Controller :
public class WAPIMailController : ApiController
{
public void PostContactUs(ContactUsModel model)
{
// Send Email Here
}
}
Thanks a lot for your help
I finally managed how to do it..
For brevity's sake, I am showing oversimplified code, see below:
Controller :
[HttpPost]
public ActionResult ContactUs(ContactUsModel model)
{
new ExternalApiCalls().MailContactUs(model);
return RedirectToAction("ContactUsSuccess", "Account");
}
Helper Class :
public void MailContactUs(ContactUsModel model)
{
client.PostAsJsonAsync("api/WAPIMail/MailContactUs", model).ConfigureAwait(false);
}
Web API Controller :
[HttpPost]
public void MailContactUs(ContactUsModel model)
{
//Email Logic Here
}