Send Query String of Current View/URL to another Action - c#

i want to send current url query string to Action but the value is empty
inside second Action
public ActionResult Edit(string userId) // start action
{
try
{
var userID = userId.Unprotect<int>("userId");
return View(model: person);
}
catch
{
return HttpNotFound();
}
}
URL
http://localhost:25388/Home/Edit?userId=MsIJTy8Ea6ixr1E3xafN2SoUkHrXon3jcUMnlHPMaTZPW7XYma5Wqtkr9JGn4Ue8PImfNw%3D%3D
and the destination action method is:
[HttpPost]
public ActionResult EditSubmit(string userID, Person person) // second action
{
var test = Request.QueryString;
return RedirectToAction("Index", "Home");
}
is there any way to receive first action/url query strings inside second action?
(I mean receive the value of userId )
userId=MsIJTy8Ea6ixr1E3xafN2SoUkHrXon3jcUMnlHPMaTZPW7XYma5Wqtkr9JGn4Ue8PImfNw%3D%3D

i reached my goal with sending current URL QueryString part with Form submit Part
here is the code:
#using (Html.BeginForm("EditSubmit", "Home", new {userId = Request.QueryString["userId"]}, FormMethod.Post))
{
<input type="submit" value="Save" class="btn btn-success btn-sm" />
}
here is the main part
Request.QueryString["userId"] (inside view)

Related

Id not being passed back to controller

The manageuser post back method is being called but the UserId is not being passed it comes back as 0. How do I correct this issue?
The html from view
<input type="image"
src="~/icons/bootstrap-icons-1.10.2/bootstrap-icons.css"
alt=""
class="bi bi-check-circle-fill fs-6"
name="btnDelete"
aria-label="Delete user"
onclick="location.href='#Url.Action("ManageUser", "ManageUsers", new {#executeAction = "Delete", #userId = #item.UserID})'" />
The controller code
[HttpGet]
public IActionResult ManageUser(string Status, string? StatusMessage)
{
TempData["Message"] = "";
if(statusMessage != null)
{
TempData["Message"] = statusMessage;
}
//load model
return View(model)
}
[HttpPost]
public IActionResult ManageUser(string executeAction, int userId)
{
string status = action;
string statusMessage = string.Empty;
if(executeAction == "Delete")
{
//delete the user
}
return RedirectToAction("ManageUser", "ManageUsers", status, statusMessage);
}
The manageuser post back method is being called but the UserId is not
being passed it comes back as 0. How do I correct this issue?
Well, as you may know Tag Helpers class generate link on page. Thus, we have either need to send request using query string or define get method on your controller action.
If you could seen in tag helper class service reference it doesn't allow httpverb by default because it takes request as URL that's query string.
Solution:
To resolve the issue either we have to define controller action as GET, just as following:
Controller:
public IActionResult ManageUser(string executeAction, int userId)
{
string status = "";
string statusMessage = string.Empty;
if (executeAction == "Delete")
{
//delete the user
}
return RedirectToAction("ManageUser", "ManageUsers", status, statusMessage);
}
View:
<input type="button"
src="~/icons/bootstrap-icons-1.10.2/bootstrap-icons.css"
alt=""
class="bi bi-check-circle-fill fs-6"
name="btnDelete"
value="Delete User"
aria-label="Delete user"
onclick="location.href='#Url.Action("ManageUser", "Some", new {#executeAction = "Delete", #userId = "111"})'" />
Note: Everything would remain same as yours.
Output:
Alternative Way:
We can directly pass our parameter using location.href what more is, it will send controller parameter as query string and will act accordingly.
Note: If you need more information about ASP.NET Core Tag Helpers, you can have a look on official document here.

How do I access the variable of one method from another method within the same class C#?

I'm working on Asp.net project. I created a Form, which asks for connectionId and holderFirstName as Input. The name of asp-action is SendProofNameRequest.
In Controller, I wrote a Method SendProofNameRequest which take connectionId and holderFirstName as Parameters. But the problem is, the purpose I'm taking holderFirstName as Input is to use this in another Method (VerifyFirstName).
So, my question is how to take holderFirstName as input from user and use this in another method / VerifyFirstName (not SendProofNameRequest).
Details.cshtml
<form class="input-group mb-3" asp-controller="Proof" asp-action="SendProofNameRequest">
<input type="hidden" name="connectionId" value="#Model.Connection.Id" />
<input type="text" name="holderFirstName" autocomplete="off" class="form-control" placeholder="Enter First Name" aria-label="First Name" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-outline-info" type="submit">Request a Proof of First Name</button>
</div>
</form>
ProofController.cs
[HttpPost]
public async Task<IActionResult> SendProofNameRequest(string connectionId, out string holderFirstName)
{
var agentContext = await _agentProvider.GetContextAsync();
var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, connectionId);
var proofNameRequest = await CreateProofNameMessage(connectionRecord);
await _messageService.SendAsync(agentContext.Wallet, proofNameRequest, connectionRecord);
return RedirectToAction("Index");
}
VerifyFirstName Method
I want to replace firstname (static value) with holderFirstName (dynamic value / user entered in form)
public bool VerifyFirstName(PartialProof proof)
{
var firstName = "Fyodor";
var name = proof.RequestedProof.RevealedAttributes.First();
if (name.Value.Raw.Equals(firstName))
{
return true;
}
return false;
}
UPDATE
As u said to add models, I did that... add the models in ViewModel page and call the #model in View page..
Now, to call the stored values in model in Verify methods controller.
VerifyProof(string proofRecordId) methods calls for another method VerifyFirstName(proof) which does the actual verification.
Kindly have a look at code and can u point out where to add model.HolderFirstName and SendNameRequestViewModel model in which method e.g. VerifyProof(string proofRecordId), VerifyFirstName(proof).. I was getting an errors..
[HttpGet]
public async Task<IActionResult> VerifyProof(string proofRecordId, SendNameRequestViewModel model)
{
var agentContext = await _agentProvider.GetContextAsync();
var proofRecord = await _proofService.GetAsync(agentContext, proofRecordId);
var request = JsonConvert.DeserializeObject<ProofRequest>(proofRecord.RequestJson);
var proof = JsonConvert.DeserializeObject<PartialProof>(proofRecord.ProofJson);
bool verified = false;
switch (request.Name)
{
case "ProveYourFirstName":
verified = VerifyFirstName(proof, model.HolderFirstName); break;
default:
break;
}
if (!verified)
{
proofRecord.State = ProofState.Rejected;
await _walletRecordService.UpdateAsync(agentContext.Wallet, proofRecord);
}
return RedirectToAction("Index");
}
public bool VerifyFirstName(PartialProof proof, SendNameRequestViewModel model.HolderFirstName)
{
var firstName = model.HolderFirstName;
var name = proof.RequestedProof.RevealedAttributes.First();
if (name.Value.Raw.Equals(firstName))
{
return true;
}
return false;
}
First of all, the actions/methods in the controller class are meant to handle requests coming from the client to the server. They're not just methods in a class.
Hence I think you need to take out out keyword from the parameter holderFirstName. Or better, to use a view model to pass between the view and the controller:
public class SendNameRequestViewModel
{
[Required]
public string ConnectionId { get; set; }
[Required]
public string HolderFirstName { get; set; }
}
public class ProofController : Controller
{
public async Task<IActionResult> SendNameRequest(string connectionId)
{
// Initialize the view model if needed, i.e., filling its ConnectionId either
// from query string or cache. I don't know how you get the connectionId
var agentContext = await _agentProvider.GetContextAsync();
var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, connectionId);
if (connectionRecord == null)
{
return NotFound();
}
var vm = new SendNameRequestViewModel
{
ConnectionId = connectionId
};
return View(vm);
}
}
Then on the view, you declare its model as SendNameRequestViewModel so that you don't have to hard code the input names/
Notes: I've also added validation summary and validation message for inputs.
#model SendNameRequestViewModel
...
<form class="input-group mb-3" method="post" asp-controller="Proof" asp-action="SendNameRequest">
<input type="hidden" asp-for="ConnectionId" />
<div asp-validation-summary="ModelOnly"></div>
<input asp-for="HolderFirstName" autocomplete="off" class="form-control"
placeholder="Enter First Name" aria-label="First Name" aria-describedby="basic-addon2">
<span asp-validation-for="HolderFirstName" class="text-danger"></span>
<div class="input-group-append">
<button class="btn btn-outline-info" type="submit">Request a Proof of First Name</button>
</div>
</form>
For your VerifyFirstName check, there are so many way to do it. You can directly run its logic in the controller action body, for example. I would create an extension method against PartialProof object:
public static class PartialProofExtensions
{
public static bool VerifyFirstName(this PartialProof proof, string firstName)
{
if (proof == null)
{
return false;
}
var name = proof.RequestedProof.RevealedAttributes
.FirstOrDefault();
return (name != null && name.Value.Raw.Equals(firstName));
}
}
When the form is posting back, you can just run the validation check in the action method:
[HttpPost]
[ValidateAntiforgeryToken]
public async Task<IActionResult> SendNameRequest(SendNameRequestViewModel model)
{
if (ModelState.IsValid)
{
var agentContext = await _agentProvider.GetContextAsync();
var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, model.ConnectionId);
if (connectionRecord == null)
{
ModelState.AddModalError("", "Invalid connection Id.");
return View(model);
}
var proofNameRequest = await CreateProofNameMessage(connectionRecord);
if (!proofNameRequest.VerifyFirstName(model.HolderFirstName))
{
ModelState.AddModalError(nameof(model.HolderFirstName), "Invalid first name.");
return View(model);
}
await _messageService.SendAsync(agentContext.Wallet, proofNameRequest, connectionRecord);
return RedirectToAction("Index");
}
return View(model);
}

Redirect back with message after file upload MVC 4 c#

I've working on MVC 4 application and want to redirect back with message to call action view:
Action that called : Upload
Current view : Index
public class HospitalController: Controller {
public ActionResult Index()
{
return View(Model);
}
[HttpPost]
public ActionResult Index(Model model)
{
return View(ohosDetailFinal);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(HttpPostedFileBase upload,FormCollection form)
{
//Here i want to pass messge after file upload and redirect to index view with message
// return View(); not working
}
}
#using (Html.BeginForm("Upload", "Hospital", null, FormMethod.Post, new { enctype = "multipart/form-data", #class = "" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<input type="file" id="dataFile" name="upload" class="hidden" />
}
Thanks !
Follow the PRG pattern. After successful processing, redirect the user to another GET action.
You can return a RedirectResult using RedirectToAction method. This will return a 304 response to the browser with the new url in the location header and the browser will make a new GET request to that url.
[HttpPost]
public ActionResult Upload(HttpPostedFileBase upload,FormCollection form)
{
//to do : Upload
return RedirectToAction("Index","Hospital",new { msg="success"});
}
Now in the Index action, you may add this new parameter msg and check the value of this and show appropriate message. The redirect request will have a querystring with key msg (Ex :/Hospital/Index?msg=success)
public ActionResult Index(string msg="")
{
//to do : check value of msg and show message to user
ViewBag.Msg = msg=="success"?"Uploaded successfully":"";
return View();
}
and in the view
<p>#ViewBag.Msg</p>
If you do not prefer the querystring in the url, you may consider using TempData. But tempdata is available only for the next request.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(HttpPostedFileBase upload,FormCollection form)
{
//Here i want to pass messge after file upload and redirect to index view with message
return Index();//or with model index
}
Try the below code, Hope It helps.!
View
#using (Html.BeginForm("Upload", "Hospital", null, FormMethod.Post, new { enctype = "multipart/form-data", #class = "" }))
{
if (TempData["Info"] != null)
{
#Html.Raw(TempData["Info"])
}
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<input type="file" id="dataFile" name="upload" class="hidden" />
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(HttpPostedFileBase upload,FormCollection form)
{
//Here i want to pass messge after file upload and redirect to index view with message
TempData["Info"]="File Uploaded Successfully!";
return RedirectToAction("Index");
}

Why can't the value of ViewBag be cleared after PostBack?

My controller name is "demo". I write 2 actions with the same name "Index". The first uses [HttpGet] and the seconds is [HttpPost].
But, when I require a PostBack from View, the value of ViewBag.Name in the action [HttpGet] public ActionResult Index() {} can't be cleared.
[HttpGet]
public ActionResult Index()
{
ViewBag.Name = "HttpGet";
return View();
}
[HttpPost]
public ActionResult Index(FormCollection form)
{
ViewBag.Name = "HttpPost";
return View();
}
In RouteConfig.cs:
routes.MapRoute(
name: "newroute",
url: "demo/index/{type}",
defaults: new { controller = "demo", action = "Index", type = UrlParameter.Optional }
);
and the View:
<form method="post" action="#Url.Action("Index", "demo", new { type = #ViewBag.Name })">
<input type="submit" value="Click me" />
</form>
#ViewBag.Name
Here is my problem: When I click the button, the value of #ViewBag.Name in the page is "HttpPost". But, in URL, it's /demo/index/HttpGet
Why?
If you navigate to this page with a GET request, you're executing method Index(), and as the page is rendered the Name is HttpGet, so it will create the URL for the form action as /demo/index/HttpGet.
Later, once you press the button, you're posting to that very URL created in the previous step, but since the form is POSTing you're executing Index(FormCollection form), and that sets Name to HttpPost. The URL remains what it was generated at the previous step.
Try it :
[HttpGet]
public ActionResult Index()
{
ViewBag.Name = "HttpGet";
return View();
}
[HttpPost]
public ActionResult Index(FormCollection form)
{
ViewBag.Name = "HttpPost";
return RedirectToAction("Index");
}

ASP.NET MVC 4 - Redirect to the same page after controller ends

From a page I have the following:
#using (Html.BeginForm("AddEntry", "Configure", FormMethod.Get, new { returnUrl = this.Request.RawUrl }))
{
#Html.TextBox("IP")
#Html.Hidden("TypeId", 1)
<input type="submit" value="#Resource.ButtonTitleAddComponent" />
}
so controller is called correctly:
public ActionResult AddEntry(string ip, int TypeId, string returnUrl)
{
// Do some stuff
return Redirect(returnUrl);
}
My problem is that returnUrl gets null and it does not redirect to the same page that called the controller. Ideas?
Using: ASP.NET MVC 4
Razor
you can also do this if you need to return to something like details page and return to the same page with a query:
return Redirect(Request.UrlReferrer.PathAndQuery);
You can get the Refer URL from the Request in the controller:
public ActionResult AddEntry(string ip, int TypeId, string returnUrl)
{
// Do some stuff
string url = this.Request.UrlReferrer.AbsolutePath;
return Redirect(url);
}
This will redirect you exactly to the calling URL.
You could use a Request.QueryString method to get some values from URL, for sample:
#using (Html.BeginForm("AddEntry", "Configure", FormMethod.Get, null))
{
#Html.TextBox("ip")
#Html.Hidden("TypeId", 1)
#Html.Hidden("returnUrl", this.Request.RawUrl)
<input type="submit" value="#Resource.ButtonTitleAddComponent" />
}
And in your controller, receive it as a parameter string returnUrl.
in your controller class use Request.UrlReferrer. There's no need to pass the url from the page.
public ActionResult AddEntry(string ip, int TypeId)
{
// Do some stuff
return Redirect(Request.UrlReferrer.ToString());
}
#using (Html.BeginForm("AddEntry", "Configure", new { returnUrl = this.Request.RawUrl }))
{
#Html.TextBox("IP")
#Html.Hidden("TypeId", 1)
<input type="submit" value="#Resource.ButtonTitleAddComponent" />
}
Change your code like this
I found that using UrlReferrer works well and allows me to add on extra params if needed.
Helper method example:
protected RedirectResult RedirectToCurrentUri(String strQueryStringOverride = "")
{
String strReferrer = Request.UrlReferrer.AbsoluteUri;
if (String.IsNullOrWhiteSpace(strReferrer))
{
strReferrer = "/";
}
// Can also override referrer here for instances where page has
// refreshed and replaced referrer with current url.
if (!String.IsNullOrWhiteSpace(strQueryStringOverride))
{
String strPath = (strReferrer ?? "").Split('?', '#')[0];
return Redirect(strPath + strQueryStringOverride);
}
return Redirect(strReferrer);
}
Note that the method allows Query String override.
This can be used as a helper method in any controller as per below:
Redirect without changing query string (if any):
return RedirectToCurrentUri()
Example query string override:
return RedirectToCurrentUri("?success=true")
on Get like Edit(int? id)
ViewBag.RefUrl = Request.UrlReferrer.ToString();
on view #Html.Hidden("RefUrl");
on post Edit(int id,string RefUrl)
return Redirect(RefUrl);

Categories

Resources