How can I pass a string from View to Controller - c#

public ActionResult Message()
{
chartstype chartname = new chartstype();
List<chartstype> listchart = new List<chartstype>();
chartname.charttype = "Column";
listchart.Add(chartname);
TempData["name"] =listchart;
TempData.Keep();
return View();
}
And I want to change my code to be able to pass a string to chartname.charttype variable from View.

you could change (or overload) the ActionMethods signature to take a string Parameter
like...
public ActionResult Message(String someVariable)
{
//do something with the contents of someVariable
chartstype chartname = new chartstype();
List<chartstype> listchart = new List<chartstype>();
chartname.charttype = "Column";
listchart.Add(chartname);
TempData["name"] =listchart;
TempData.Keep();
return View();
}
which could be called like https://www.example.com/Message?someVariable=someString

In controller
public ActionResult Message(String chartName)
{
chartstype chartname = new chartstype();
List<chartstype> listchart = new List<chartstype>();
chartname.charttype = chartName;
listchart.Add(chartname);
TempData["name"] =listchart;
TempData.Keep();
return View();
}
URL :https://www.example.com/Message?chartName=ABCD

public ActionResult Message(string message)
and make sure to see if string is null, because anyone can call this method trough url.
if(string.IsNullOrWhiteSpace(message))
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);
}
And then code in view
<form action="/controlerName/Message" method="get or post , get is by default if you don't put this atribute">
<input id="txt1" type="text" name="message" value="set value here or in JS or let user enter value"/>
If you don't want textbox to be seen use
<input type="hidden" name="message" value="somevalue"/>
Unless you want to call your method from javaScript using ajax?

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);
}

Passing Data from one controller method to another in MVC

I have a page that has 2 text boxes First Name and last Name after user click on sign up button API will run and returns user info and shows another page(view) that had user Phone, email,.. That fill with the info that API returns. I have 1 controller and 2 views.
I get the info from API and return the second view but not sure how fill the text boxes with the info I have. The problem is using the models in view, I have 2 models one for each view. I am getting this error when I call the second view:
The model item passed into the dictionary is of type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]', but this dictionary requires a model item of type Models.CreateLogInRequest'.
This is my controller:
[HttpGet]
public ActionResult SearchUser()
{
return View();
}
[HttpPost]
public async Task<ActionResult> SearchUser(UserSearchRequest userSearchRequest)
{
HttpClient client = new HttpClient();
object userObject = null;
string baseUrl = "http://test/api/users";
if (userSearchRequest.FirstName != null && userSearchRequest.LastName)
{
var response = await client.GetAsync(string.Format("{0}{1}/{2}/{3}", baseUrl, "/users", userSearchRequest.FirstName, userSearchRequest.LastName));
if (response.IsSuccessStatusCode)
{
userObject = new JavaScriptSerializer().DeserializeObject(response.Content.ReadAsStringAsync().Result) as object;
}
}
if (userObject != null)
{
return View("Create", userObject);
}
return View("Create", null);
}
[HttpPost]
public ActionResult Create(CreateLogInRequest createLogInRequest)
{
return View();
}
This is my First View that shows 2 text boxes:
#using (Html.BeginForm("SearchUser", "SignUp", FormMethod.Post))
{
#Html.AntiForgeryToken()
<input id="FirstName" name="FirstName" type="text" placeholder="First NAME" />
<input id="LastName" name="LastName" type="text" placeholder="LastName " />
<input id="btnSubmit" name="btnSubmit" type="submit" value="SIGN UP TODAY" />
}
and this is my model for 1st view:
public class UserSearchRequest
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This is the second View:
#model Models.CreateLogInRequest
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm("create", "SignUp", FormMethod.Post))
{
#Html.AntiForgeryToken()
<input id="Email" name="Email" type="text" placeholder="Email" value="#Model.Email" />
<input id="Phone" name="Phone" type="text" placeholder="Phone" value="#Model.Phone" />
<input id="btnSubmit" name="btnSubmit" type="submit" value="CREATE ACCOUNT" />
}
and this is Model for this view:
public class CreateLogInRequest
{
public string Email { get; set; }
public string Phone { get; set; }
....
}
See my comments and try this:
[HttpGet]
public ActionResult SearchUser()
{
return View();
}
[HttpPost]
public async Task<ActionResult> SearchUser(UserSearchRequest userSearchRequest)
{
HttpClient client = new HttpClient();
CreateLogInRequest userObject = null;
string baseUrl = "http://test/api/users";
if (userSearchRequest.FirstName != null && userSearchRequest.LastName)
{
var response = await client.GetAsync(string.Format("{0}{1}/{2}/{3}", baseUrl, "/users", userSearchRequest.FirstName, userSearchRequest.LastName));
if (response.IsSuccessStatusCode)
{
userObject = new JavaScriptSerializer().DeserializeObject<CreateLogInRequest>(response.Content.ReadAsStringAsync().Result);
}
}
if (userObject != null)
{
return RedirectToAction("Create", userObject);
}
return View("Create", null);
}
[HttpPost]
public ActionResult Create(CreateLogInRequest createLogInRequest)
{
return View();
}
In the Controller you can create a new instance of Models.CreateLogInRequest model and fill the related properties received from 1st View. If Models.CreateLogInRequest does not contain such properties then it is better to load these values by using TempData or ViewBag in the Controller retrieved from the 1st View and pass them to the 2nd View. For the differences between ViewBag, ViewData, or TempData you might have a look at When to use ViewBag, ViewData, or TempData in ASP.NET MVC 3 applications. Hope this helps...

ViewModel Not Working

[HttpPost]
public ActionResult AddToCart(int phoneListingID, string sellerSKU)
{
ShoppingBasket shoppingBasket = new ShoppingBasket();
BasketItem currentItem = new BasketItem
{
sellerID = 1,
Price = 100,
Quantity = 1,
sellerSKU = "testsku"
};
shoppingBasket.AddtoBasket(currentItem, this.HttpContext);
var viewModel = new BasketViewModel
{
basketItems = ShoppingBasket.GetBasketItems(this.HttpContext),
basketTotal = ShoppingBasket.GetBasketTotal(this.HttpContext)
};
return View(viewModel);
}
My form:
#using (Html.BeginForm("AddToCart","ShoppingBasket",new { phoneListingID = 12345, sellerSKU = "test"}, FormMethod.Post ))
{
<input type="submit" value="AddToCart" />
}
The expected result is that my BasketViewModel page is returned, however the view being returned is ShoppingBasket/AddToCart?PhoneID=xxxx&sellerSKU=xxxx
What am I doing wrong?
In MVC Suppose your action is like
public ActionResult MyAction()
{
return View();
}
In this scenerio it will point to the view named 'MyAction'. If you want to send it to another view make it like
public ActionResult MyAction()
{
return View("MyViewName");
}
If you want to pass some model to make it like
public ActionResult MyAction()
{
return View("MyViewName",model); // Here model is your object of model class
}
In you snippet your are returning default i.e. 'AddToCart' view because you are not describing explicitly. Make your code like
return View("BasketViewModel",viewModel); // where BasketViewModel is your view name
You're returning that controller's View, if you wish to transfer to another view try
return BasketViewActionResult(viewmodel)
Then access your 'BasketViewActionResult'
Function BasketViewActionResult(model as BasketViewModel) as ActionResult
return View(model)
End Function
Sorry if you don't get VB, I can translate it to C# for you if you wish.
Edit:
You can also simply change the form's action.
#using (Html.BeginForm("BasketView","ShoppingBasket",...
and make all your manipulations within that actionresult

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