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.
Related
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
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;
}
}
I'm making a site with external authorization through VK, I've looked through a lot of examples, but I ran into one problem, in all examples redirection to ExternalLoginCallback happens through Challange method with provider parameters and url, but redirection happens not to specified url, but to signin-vkontakte-token, which is specified in ConfigureServices. What can this be related to?(It doesn't matter if you give me an answer with the specified provider or another one, such as Facebook)
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl)
{
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Home", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction("Index");
}
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, false);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}
This is the basic code snippet !!
Show me the Login page if none of the user is signedIn. If any user is active it should redirect to Index Page of Home Controller and should not show Login page !!
public class AccountController : CommonController
{
public AccountController(IOptions<ConnectionSetting> connString) : base(connString)
{
}
public IActionResult Index()
{
return RedirectToAction("Index", "Home");
}
[HttpGet]
[AllowAnonymous]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(User user)
{
if (ValidateUser(user.UserName , user.Password))
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name , user.UserName)
};
//Now Create an ClaimIdentity
var claimsIdentity = new ClaimsIdentity(claims, "BloggingCookie");
//Create Claim Principal using that Identity
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
await HttpContext.SignInAsync("BloggingCookie", principal );
return RedirectToAction("Index", "Home");
}
else
{
ViewData["Status"] = "Invalid Username or Password";
return View();
}
}
}
All you need is to add something like the following to the top of your login action:
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Manage");
}
You can of course redirect to wherever you like.
Is there an easy way to convert an IdentityResult to an IActionResult taking into account errors?
IdentityResult is just a class which tells you if an ASP.NET (Core) Identity operation succeeded or not and in case of an error offers you error messages and is unrelated to MVC Action's results which implement IActionResult interface.
If you use WebApi/RestApi controllers , you'd translate it to something like
public IActionResult SomeActionName()
{
IdentityResult result = ...; // some identity operation
// all is okay, return http code 200
if(result.Success)
return Ok();
// error happened, return http code 400 + errors as json
return BadRequest(result.Errors);
}
Or if you are really lazy, write your own IActionResult:
public class IdentityActionResult : IActionResult
{
private readonly IdentityResult identityResult;
public IdentityActionResult(IdentityResult identityResult)
{
this.identityResult = identityResult;
}
public Task ExecuteResultAsync(ActionContext context)
{
IActionResult actionResult = null;
if(identityResult.Success)
{
actionResult = new OkResult();
}
else
{
actionResult = new BadRequestObjectResult(identityResult.Errors);
}
return actionResult.Execute(context);
}
}
Of course this can be further optimized so that you don't have to create two IActionResult objects per request, but that's an exercise left up to you ;)
You can write an extension method for IdentityResult which returns ObjectResult something like this:
public static class IdentityResultExtension
{
public static ObjectResult ToObjectResult(this IdentityResult result)
{
//
return new ObjectResult(result);
}
}
then use it in action:
public IActionResult YourAction()
{
IdentityResult result;
return result.ToObjectResult();
}