ASP.NET MVC 4 ViewBag value incremented only once - c#

Hy!
I have a very interesting problem. I have a button and if a user clicks on that button it will reload that page, incrementing the value which is stored in the viewbag and write it on the screen. When the user clicks on the button, the value of the number incremented only once and I don't know why. The codes are very simple:
The controller:
public ActionResult Index()
{
ViewBag.number= 0;
return View();
}
[HttpPost]
public ActionResult Index(int number)
{
ViewBag.number= number;
return View();
}
The view:
#{
int number= ViewBag.number;
number++;
}
#using (Html.BeginForm("Index","Default", FormMethod.Post))
{
#Html.Hidden("number",number)
#Html.Display("number",number);
<input type="submit" value="Ok" />
}
Thanks for your reply! :)

I couldn't see any issue with your code.
However, If you replace your code on view to below, I think this should work.
#using (Html.BeginForm("Index","Home", FormMethod.Post))
{
<input type="hidden" name="number" value="#number" />
#Html.Display("number", number)
<input type="submit" value="Ok" />
}
But not sure what is the difference between the Html.Hidden and directly writing the input tag.

ViewBag is supposed to be used to pass data from controller to view (dynamic alternative of ViewData).To store data between requests use session or TempData

Related

Cannot apply indexing with [] to an expression of type HttpRequest

I am quite new to programming and I'm trying to learn asp.net web development. I am trying to create a form to take in a username and password which it should then send to the accompanying post action method however when I try to request the data from the action method it comes up with an error saying, 'Cannot apply indexing with [] to an expression of type HttpRequest'. I really don't know what im doing and would appreciate it if someone can tell me what im doing wrong. Thanks!
This is the HTML
#{
ViewData["Title"] = "Login";
}
<div class="text-center">
<form method="post" action="Index">
<label for="username">Username: </label>
<input type="text"id="username" />
<label for=" password">Password: </label>
<input type ="text"id="password" />
<input type="submit" value="Submit"/>
</form>
</div>
This is the action method
public IActionResult Index()
{
return View();
}
[HttpPost]
[ActionName("Index")]
public IActionResult IndexPost()
{
string username = Request["username"]; #This is where the error is happening
string password = Request["password"]; #Red line under both requests
-stuff to do-
return Content("");
}
ASP.Net has model binding that can be used to automagically bind Action parameters to values POSTed so you should be able to do this
[HttpPost]
[ActionName("Index")]
public IActionResult IndexPost(string username, string password)
{
-stuff to do-
return Content("");
}
The reason for the error is that Request is not indexable like a Dictionary.

List hidden value passes wrong value to controller

I have a list In my view. For each row, I view button and I am passing Id value as hidden. But when I click any button it is passing wrong hidden value to the controller. Always it passes the first-row hidden value to the controller.
View:
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</div>
</div>
}
Controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string viewId)
{
return RedirectToAction("ViewDetails");
}
To get all values you need to change the input value type in your controller to array of strings.
I hope that this solution can help you
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string[] viewId)
{
return RedirectToAction("ViewDetails");
}
if you want to get the exact value you need to duplicate the form within your foreach
in this case you should write somthing like this :
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<form ... > // complete your form attributes
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</form>
</div>
</div>
}
Note : You should delete the global form
You should have one form for each row. then you submit that row.
Otherwise as you state it passes first value.
You are setting each value to the same element ID (which is invalid anyway) and name. When you submit your form (which would be more helpful to fully answer your question) it is finding the first element that matches that criteria and submitting it.
There are multiple ways to resolve this such as the already mentioned form per entry but the other preference would be to modify you button to a div and add a click handler to pass the specific value to a js function which would then submit to the controller. Its a preference choice regarding how tightly coupled you want your front end. But the main problem is your element naming convention.

couldn't get model in action on post?

I have a strongly typed view which has text fields and a submitted link. After editing data I press link and try to submit form. Placing a break point I am able to see control comes to action; modle is not null but all of its properties are always null, not sure where I m doing wrong. My tiny view code is:
#model BL.Model.Speaker
#using (Html.BeginForm())
{
<table>
<tr>
<td>#Html.EditorFor(s => #Model.Name)</td>
<td>#Html.EditorFor(s => #Model.Email)</td>
</tr>
</table>
#Html.ActionLink("Submit", "All");
}
and my controller action is:
public ActionResult All(Speaker model){
return View(database.Speakers.FirstOrDefault());
}
Help please
You should change your button from ActionLink to a submit button like this
#Html.ActionLink("Submit", "All");
By
<input type="submit" value="submit"/>
Also change your Action to recieve the data by post
[HttpPost]
public ActionResult All(Speaker model)
{
return View(database.Speakers.FirstOrDefault());
}

input text on postback returing NULL?

Can someone please tell me why the id of the checkbox 'userId' returns null on POST
<input type='checkbox' onclick='$("#userId").val("#user.Id"); return true; '/>
#using (Html.BeginFormAntiForgeryPost(Url.Action("Index", "ChangeUserAccount"), FormMethod.Post))
{
<input type="text" id="userId" />
<input type="submit" id="btn" name="btnSubmit" value="Update" style="float:right;" />
}
[HttpPost, ActionName("Index")]
[Authorize]
public ActionResult IndexPOST(UserLoginRecordIndexVM model, int? userId)
{
So on screen the text box contains the correct ID of the checkbox, but when I click the 'Update' button NULL gets returned??
Why don't you leverage this helper:
#Html.TextBox("userId", null, new { id = "userId" });
This will add the appropriate id and name attributes to your textbox.
Just add the name attribute:
<input type="text" id="userId" name="userId" />
But, also make sure your action accepts it as a parameter, string userId, or that it's part of the model that's posted back. So, in your case you might just do this:
public ActionResult IndexPOST(UserLoginRecordIndexVM model, string userId)

MVC razor form with multiple different submit buttons?

A Razor view has 3 buttons inside a form. All button's actions will need form values which are basically values coming input fields.
Every time I click any of buttons it redirected me to default action. Can you please guide how I can submit form to different actions based on button press ?
I really appreciate your time, guidance and help.
You could also try this:
<input type="submit" name="submitbutton1" value="submit1" />
<input type="submit" name="submitbutton2" value="submit2" />
Then in your default function you call the functions you want:
if( Request.Form["submitbutton1"] != null)
{
// Code for function 1
}
else if(Request.Form["submitButton2"] != null )
{
// code for function 2
}
This elegant solution works for number of submit buttons:
#Html.Begin()
{
// Html code here
<input type="submit" name="command" value="submit1" />
<input type="submit" name="command" value="submit2" />
}
And in your controllers' action method accept it as a parameter.
public ActionResult Create(Employee model, string command)
{
if(command.Equals("submit1"))
{
// Call action here...
}
else
{
// Call another action here...
}
}
in the view
<form action="/Controller_name/action" method="Post>
<input type="submit" name="btn1" value="Ok" />
<input type="submit" name="btn1" value="cancel" />
<input type="submit" name="btn1" value="Save" />
</form>
in the action
string str =Request.Params["btn1"];
if(str=="ok"){
}
if(str=="cancel"){
}
if(str=="save"){
}
You can use JS + Ajax.
For example, if you have any button you can say it what it must do on click event.
Here the code:
<input id="btnFilterData" type="button" value="myBtn">
Here your button in html:
in the script section, you need to use this code (This section should be at the end of the document):
<script type="text/javascript">
$('#btnFilterData').click(function () {
myFunc();
});
</script>
And finally, you need to add ajax function (In another script section, which should be placed at the begining of the document):
function myFunc() {
$.ajax({
type: "GET",
contentType: "application/json",
url: "/myController/myFuncOnController",
data: {
//params, which you can pass to yu func
},
success: function(result) {
error: function (errorData) {
}
});
};
This is what worked for me.
formaction="#Url.Action("Edit")"
Snippet :
<input type="submit" formaction="#Url.Action("Edit")" formmethod="post" value="Save" class="btn btn-primary" />
<input type="submit" formaction="#Url.Action("PartialEdit")" formmethod="post" value="Select Type" class="btn btn-primary" />
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit( Quote quote)
{
//code
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PartialEdit(Quote quote)
{
//code
}
Might help some one who wants to have 2 different action methods instead of one method using selectors or using client scripts .
The cleanest solution I've found is as follows:
This example is to perform two very different actions; the basic premise is to use the value to pass data to the action.
In your view:
#using (Html.BeginForm("DliAction", "Dli", FormMethod.Post, new { id = "mainForm" }))
{
if (isOnDli)
{
<button name="removeDli" value="#result.WeNo">Remove From DLI</button>
}
else
{
<button name="performDli" value="#result.WeNo">Perform DLI</button>
}
}
Then in your action:
public ActionResult DliAction(string removeDli, string performDli)
{
if (string.IsNullOrEmpty(performDli))
{
...
}
else if (string.IsNullOrEmpty(removeDli))
{
...
}
return View();
}
This code should be easy to alter in order to achieve variations along the theme, e.g. change the button's name to be the same, then you only need one parameter on the action etc, as can be seen below:
In your view:
#using (Html.BeginForm("DliAction", "Dli", FormMethod.Post, new { id = "mainForm" }))
{
<button name="weNo" value="#result.WeNo">Process This WeNo</button>
<button name="weNo" value="#result.WeNo">Process A Different WeNo This Item</button>
}
Then in your action:
public ActionResult DliAction(string weNo)
{
// Process the weNo...
return View();
}
Try wrapping each button in it's own form in your view.
#using (Html.BeginForm("Action1", "Controller"))
{
<input type="submit" value="Button 1" />
}
#using (Html.BeginForm("Action2", "Controller"))
{
<input type="submit" value="Button 2" />
}
You could use normal buttons(non submit). Use javascript to rewrite (at an 'onclick' event) the form's 'action' attribute to something you want and then submit it. Generate the button using a custom helper(create a file "Helper.cshtml" inside the App_Code folder, at the root of your project) .
#helper SubmitButton(string text, string controller,string action)
{
var uh = new System.Web.Mvc.UrlHelper(Context.Request.RequestContext);
string url = #uh.Action(action, controller, null);
<input type=button onclick="(
function(e)
{
$(e).parent().attr('action', '#url'); //rewrite action url
//create a submit button to be clicked and removed, so that onsubmit is triggered
var form = document.getElementById($(e).parent().attr('id'));
var button = form.ownerDocument.createElement('input');
button.style.display = 'none';
button.type = 'submit';
form.appendChild(button).click();
form.removeChild(button);
}
)(this)" value="#text"/>
}
And then use it as:
#Helpers.SubmitButton("Text for 1st button","ControllerForButton1","ActionForButton1")
#Helpers.SubmitButton("Text for 2nd button","ControllerForButton2","ActionForButton2")
...
Inside your form.
Simplest way is to use the html5 FormAction and FormMethod
<input type="submit"
formaction="Save"
formmethod="post"
value="Save" />
<input type="submit"
formaction="SaveForLatter"
formmethod="post"
value="Save For Latter" />
<input type="submit"
formaction="SaveAndPublish"
formmethod="post"
value="Save And Publish" />
[HttpPost]
public ActionResult Save(CustomerViewModel model) {...}
[HttpPost]
public ActionResult SaveForLatter(CustomerViewModel model){...}
[HttpPost]
public ActionResult SaveAndPublish(CustomerViewModel model){...}
There are many other ways which we can use, see this article ASP.Net MVC multiple submit button use in different ways
As well as #Pablo's answer, for newer versions you can also use the asp-page-handler tag helper.
In the page:
<button asp-page-handler="Action1" type="submit">Action 1</button>
<button asp-page-handler="Action2" type="submit">Action 2</button>
then in the controller:
public async Task OnPostAction1Async() {...}
public async Task OnPostAction2Async() {...}
Didn't see an answer using tag helpers (Core MVC), so here it goes (for a delete action):
On HTML:
<form action="" method="post" role="form">
<table>
#for (var i = 0; i < Model.List.Count(); i++)
{
<tr>
<td>#Model.List[i].ItemDescription</td>
<td>
<input type="submit" value="REMOVE" class="btn btn-xs btn-danger"
asp-controller="ControllerName" asp-action="delete" asp-route-idForDeleteItem="#Model.List[i].idForDeleteItem" />
</td>
</tr>
}
</table>
</form>
On Controller:
[HttpPost("[action]/{idForDeleteItem}"), ActionName("Delete")]
public async Task<IActionResult> DeleteConfirmed(long idForDeleteItem)
{
///delete with param id goes here
}
Don't forget to use [Route("[controller]")] BEFORE the class declaration - on controller.
Information acquired from:
http://www.codedigest.com/posts/46/multiple-submit-button-in-a-single-form-in-aspnet-mvc
For you chaps coming more recently, you can use the HTML 5 Formaction Attribute.
In your <input> or <button>
Just define:
<button id="btnPatientSubmit" type="submit" class="btn btn-labeled btn-success" formaction="Edit" formmethod="post">
Notice the addition of formation= "Edit", this specifies which ActionResult I want to submit to in my controller.
This will allow you to have multiple submit buttons, where each could submit to independent ActionResults (Methods) in your controller.
This answer will show you that how to work in asp.net with razor, and to control multiple submit button event. Lets for example we have two button, one button will redirect us to "PageA.cshtml" and other will redirect us to "PageB.cshtml".
#{
if (IsPost)
{
if(Request["btn"].Equals("button_A"))
{
Response.Redirect("PageA.cshtml");
}
if(Request["btn"].Equals("button_B"))
{
Response.Redirect("PageB.cshtml");
}
}
}
<form method="post">
<input type="submit" value="button_A" name="btn"/>;
<input type="submit" value="button_B" name="btn"/>;
</form>
In case you're using pure razor, i.e. no MVC controller:
<button name="SubmitForm" value="Hello">Hello</button>
<button name="SubmitForm" value="World">World</button>
#if (IsPost)
{
<p>#Request.Form["SubmitForm"]</p>
}
Clicking each of the buttons should render out Hello and World.

Categories