How to update textbox value - asp.net-mvc

I have a textbox in my View. I input a number into the textbox, and then i want the controller to multiply the number and put the result into the textbox.
How can I do that?
This is what i have done already.
Let's start with the View:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<h2>Please enter a number</h2>
<% using (Html.BeginForm()) { %>
<%=Html.TextBox("number")%>
<input type="submit" value="Index" name ="Index" />
<% } %>
</div>
</body>
</html>
As you can see I have a simple textbox and button.
This is my controller:
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(int number)
{
number = number * 2;
ViewData["number"] = number;
return View(ViewData);
}
}
}
But nothing really happens. Yeah, I see the Post is being done, and the coded steps into public ActionResult Index(int number). I see that the number is taken from the textbox, it's multiplied correctly.
I've tried using ViewData as you can see. I've also used TempData.
This is another code for the textbox in the View I've tried:
<%=Html.TextBox("number", ViewData["number"])%>
But it doesn't matter. The textbox doesn't get updated with the new value. How can I do that?

Try
[HttpPost]
public ActionResult Index(int number)
{
number = number * 2;
ViewData["id"] = number;
ModelState.Clear(); // this is the key, you could also just clear ModelState for the id field
return View(ViewData);
}
You can also just use a regular html input instead of the HtmlHelper and your code would work as expected.
The default behavior of the Html helper is biting you. It looks for data in ModelState collection before using what is in ViewData. The reasoning is the normal case is a POST > Validation Fail > Return View, so showing the data the user entered is the intended behavior.

Related

Select Tag Helper Works for SelectedAlertIndex, but LoadAlert() action doesn't load new view page

This is my form in AlertSelect.cshtml:
#model edxl_cap_v1_2.Models.ContentViewModels.AlertViewModel
#{
ViewData["Title"] = "AlertSelect";
Layout = "~/Views/Shared/_CapCategoryLayout.cshtml";
}
<head>
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
</head>
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form>
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<asp-controller ="Alerts" asp-action="LoadAlert" method="post">
<br />
<input type="submit" name="LoadAlert" value="LoadAlert" />
</form>
}
And this is my LoadAlert() controller action:
[HttpPost]
public IActionResult LoadAlert(Alert obj, string LoadAlert)
{
if (!string.IsNullOrEmpty(LoadAlert))
{
ViewBag.Message = "Alert loaded successfully";
}
return View("/Views/Alerts/Index", obj);
}
AlertSelect.cshtml displays the standard header and left column and the drop down list and when selected and submitted, the page resets instead of displaying /Views/Alerts/Index.cshtml with the data filled in correctly. However the url reflects the selected item: http://localhost:61453/alerts/AlertSelect?SelectedAlertIndex=2&LoadAlert=LoadAlert.
I'm close but clearly missing something and any help would very welcome. I'd also like to display the selected item on the index.cshtml page to reinforce for the user the alert message they're working on, but the viewmodel (with two properties) for the Select Tag Helper is different from the model (with 16 properties) for the index page.
Made the change to my form per both comments and answer below, and instead of returning the view specified in LoadAlert() I have a mismatch of models: "InvalidOperationException:
The model item passed into the ViewDataDictionary is of type
'edxl_cap_v1_2.Models.Alert', but this ViewDataDictionary instance requires
a model item of type 'System.Collections.Generic.IEnumerable`1[edxl_cap_v1_2.Models.Alert]'.
AlertSelect.cshtml specifies:
#model edxl_cap_v1_2.Models.ContentViewModels.AlertViewModel
Alert.cs specifies:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace edxl_cap_v1_2.Models
{
public class Alert
{
[Key]
public int AlertIndex { get; set; }
[MaxLength(150)]
public string Alert_Identifier { get; set; }
public string Sender { get; set; }
public DateTime Sent { get; set; }
...
/Views/Alerts/Index.cshtml specifies:
#model IEnumerable<edxl_cap_v1_2.Models.Alert>
#using edxl_cap_v1_2.Models
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_CapCategoryLayout.cshtml";
}
and _CapCategoryLayout specifies:
#model edxl_cap_v1_2.Models.ContentViewModels.AlertViewModel
<!DOCTYPE html>
I'm still not seeing where
The model item passed into the ViewDataDictionary is of type
'edxl_cap_v1_2.Models.Alert'
comes into play except as the namespace of Alert.cs. What do I need to change to keep out of these type mismatches?
The correct way to define form tag helpers in Core MVC should be like this (see documentation here):
<form asp-controller="Alerts" asp-action="LoadAlert" method="post">
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="LoadAlert" value="LoadAlert" />
</form>
Note that default form submit method is GET if unspecified, as described in form element definition:
method = get|post [CI]
This attribute specifies which HTTP method will
be used to submit the form data set. Possible (case-insensitive)
values are "get" (the default) and "post".
The GET method will pass form values through URL with query string, hence you get the URL like following:
http://localhost:61453/alerts/AlertSelect?SelectedAlertIndex=2&LoadAlert=LoadAlert
Since no HttpGetAttribute action method found with those 2 query string parameters, the page will "reset" and displaying the same form again instead returning another view.

MVC Controller Action called from PartialView in _Layout.cshtml

In my _Layout.cshtml I want to include a dropdown list in the site header. I'm not positive of the best way to do this, but I've tried to code it using a PartialView. It seems to be working, but when the form is submitted the page loads with only the dropdownlist.
ViewModel:
namespace XXXX_Web_App.Models
{
public class LanguageListPartial
{
[DataType(DataType.Text)]
[Display(Name = "Language")]
public string Language { get; set; }
}
}
Controller:
[AllowAnonymous]
[ChildActionOnly]
public ActionResult LanguageList()
{
ViewBag.LanguageList = GetLanguageList();
return PartialView("_LanguageListPartial");
}
[AllowAnonymous]
[HttpPost]
public async Task<ActionResult> LanguageList(string language)
{
// Save selection to cookie
HttpCookie cookie = new HttpCookie("UserSettings");
cookie["Language"] = language;
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
// Save selection to user profile
if (User.Identity.IsAuthenticated)
{
String userId = User.Identity.GetUserId();
ApplicationUser user = await UserManager.FindByIdAsync(userId);
user.Language = language;
await UserManager.UpdateAsync(user);
}
ViewBag.LanguageList = GetLanguageList();
return PartialView("_LanguageListPartial");
}
public List<SelectListItem> GetLanguageList()
{
List<SelectListItem> languages = new List<SelectListItem>();
languages.Add(new SelectListItem { Text = "English", Value = "en-US" });
languages.Add(new SelectListItem { Text = "Français", Value = "fr-CA" });
languages.Add(new SelectListItem { Text = "Português", Value = "pt-BR" });
languages.Add(new SelectListItem { Text = "Español", Value = "es-MX" });
return languages;
}
Partial View:
#model XXXX_Web_App.Models.LanguageListPartial
#Html.DropDownListFor(
x => x.Language,
new SelectList(ViewBag.LanguageList, "Value", "Text"),
new { #class = "form-control toggle", onchange = "this.form.submit();"
})
_Layout.cshtml:
#using Westwind.Globalization;
#using Westwind.Globalization.Resources;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryUI")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
<script src="/Scripts/jquery.cookie.js"></script>
</head>
<body>
<div style="">
<div class="header container">
... nav menu ...
</div>
<form action="/Account/LanguageList" method="post" >
#{Html.RenderAction("LanguageList", "Account");}
</form>
<div class="container">
<div class="row">
<div class="col-md-12">
#RenderBody()
</div>
</div>
</div>
<footer class="container">
<hr />
<p>© #DateTime.Now.Year</p>
</footer>
</div>
</body>
</html>
The desired logic is:
Every site/page visit
Anonymous user - load selection from cookie. Default to English. (not done yet)
Authenticated user - load selection from user profile (not done yet)
On selection
Anonymous user - save selection to cookie
Authenticated user - save selection to cookie and update user profile
Like I said, this seems to be working except that when a selection is made the Controller action gets called and when the page reloads the only thing on the page is the dropdown list.
How do I return the View in this situation?
One other question, I would like the text in the dropdown list items to include the culture specific decorations, but they are displaying literally like Français instead. I don't see how I can use Html.Encode() in this situation. It's probably being caused by the way I am adding the items in GetLanguageList(). How do I avoid this?
EDIT
To clarify, my excerpt from _Layout.cshtml above is just that - an excerpt. My _Layout.cshtml contains what you might expect of it - a header with logo and subtitle, navigation menu, and RenderBody() code. The page displays properly on the Partial View's GET Controller Action, but when I make a selection from the dropdown list the POST Controller Action only the dropdown list is displayed on the page - nothing else. _Layout.cshtml is gone and so are the contents of whatever page I am on.
When you submit the form the /Account/LanguageList action is called. It returns with only a partial view:
return PartialView("_LanguageListPartial");
When you return just this, your _layout file is not called.
So what you want is to return another view. Unless you specify it, all your views will contain your _layout.cshtml file. And that already contains the partial view.
So create a new view and return that when you post to the form.

TextBox(HtmlHelper, String) - is view model also searched for a value?

Pro Asp.Net MVC 4 (pg 535):
The string argument is used to search the view data, ViewBag and view
model to find a corresponding data item that can be used as the basic
for the input element. So, for example, if you call
#Html.TextBox("DataValue"), the MVC Framework tries to find some
item of data that corresponds with the key DataValue. The following
locations are checked: • ViewBag.DataValue • #Model.DataValue
Book states that an overload of a Html.TextBox which takes a single string argument checks both ViewData and view model to obtain the value for display. But after experimenting a little, it seems it only checks ViewData for a value, but not also a view model.
Thus, in the output generated from Html.TextBox the value attribute is set to an empty string:
public class Person
{
public string FirstName = "Leila";
}
*.cshtml:
#model HelperMethods.Models.Person
...
#Html.TextBox("FirstName")
Output:
...
<input id="FirstName" name="FirstName" type="text" value="" />
So is the book wrong and TextBox(HtmlHelper, String) checks only ViewData or does it also check a view model?
UPDATE:
public class Person
{
public string FirstName = "Leila";
}
public class HomeController : Controller
{
public ActionResult Index()
{
return View((object)new Person());
}
}
Index.cshtml:
#model Mvc4.Controllers.Person
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
#Html.TextBox("FirstName")
</body>
</html>
Much appreciated
Just did a quick test and it seems that it has to be a property and not a field.
So this should work:
public class Person
{
public string FirstName { get; set; }
}

In MVC view, when form is posted, request contains form values while all model fields are 0

Using Visual Studio 2010, MVC project
When my form is submitted (currently via javascript, but same results with a submit button), the action is getting an empty model with both of the fields in it being zero instead of containing the value I entered into the textbox. The Request object does contain the correct name/value pair in the Form collection.
Model values going the other way work fine - so based on my [HttpGet] CallDisplayHome() action, the form loads with the textbox value being 1.
If anyone has a clue as to why it would not work coming back via POST, I would sure appreciate it.
Model being used:
namespace TCSWeb.Models
{
public class CallDisplayModel
{
public int SelectedRowIndex;
public int SelectedLineID;
}
}
View:
#model TCSWeb.Models.CallDisplayModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<body>
/*
There a Jscript datatable here and a bunch of scripts for working with it in the header I am skipping because I am hoping they are not relevant
*/
<div>
#using (Html.BeginForm("Testing", "CallDisplay", FormMethod.Post, new { name = "submitSelLine" }))
{
#Html.TextBoxFor(m => m.SelectedLineID)
<p>
<input type="submit" value="Log On" />
</p>
}
</div>
<button onclick="SubmitSelCallRecord()">#LangRes.Strings.calldisplay_opencallrecord</button>
My controller actions:
[HttpGet]
public ActionResult CallDisplayHome()
{
TCSWeb.Models.CallDisplayModel temper = new CallDisplayModel();
temper.SelectedLineID = 1;
temper.SelectedRowIndex = 1;
return View(temper);
}
[HttpPost]
public ActionResult Testing(TCSWeb.Models.CallDisplayModel cdmodel)
{
return RedirectToAction("CallDisplayHome"); //breaking here, cmodel has zero for selectedlineid
}
You need to declare your CallDisplayModel variables as properties:
public int SelectedRowIndex { get; set; }
[Required]
public int SelectedLineID { get; set; }
You can also add a little bit of validation to make sure that the user provides the correct information.
Change your post method to the following:
[HttpPost]
public ActionResult Testing(TCSWeb.Models.CallDisplayModel temper)
{
//check if valid
if(ModelState.IsValid)
{
//success!
return RedirectToAction("CallDisplayHome");
}
//update error! redisplay form
return View("CallDisplayHome", temper);
}
And display the errors in your view like so:
#Html.ValidationMessageFor(m => m.SelectedLineID)
#Html.TextBoxFor(m => m.SelectedLineID)
I'm unsure what your submitSelCallRecord button is doing, as it is referencing the javascript that was omitted.

Why can't I HtmlDecode in ASP.NET MVC 3

Here is the scenario. I want to use CKEditor for a rich text field on a form, but for whatever reason I cannot get the contents from the textarea to the server and back to the page without encoding problems. Here is the little sample program I wrote up to try and figure out what is going on. First, my view model:
HomeViewModel.cs
namespace CkEditorTest.Models
{
public class HomeViewModel
{
[Required]
[DataType(DataType.Html)]
[Display(Name = "Note")]
public string Note { get; set; }
}
}
Now my controller:
HomeController.cs
using System.Web.Mvc;
using CkEditorTest.Models;
namespace CkEditorTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new HomeViewModel());
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Index(HomeViewModel model)
{
return View(model);
}
}
}
And finally, my view:
Index.cshtml
#model CkEditorTest.Models.HomeViewModel
#{
ViewBag.Title = "CKEditor Test";
}
#section head
{
<script type="text/javascript" src="#Url.Content("~/Scripts/ckeditor/ckeditor.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/ckeditor/adapters/jquery.js")"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#Note").ckeditor();
});
</script>
}
<h2>CKEditor Test</h2>
#using (Html.BeginForm())
{
#Html.LabelFor(m => m.Note)<br /><br />
#Html.TextAreaFor(m => m.Note)<br />
<input type="submit" />
}
#if (!String.IsNullOrEmpty(Model.Note))
{
<div id="noteText">#Model.Note</div>
}
No matter what I do, I cannot display the Model.Note property as html on my view. By the time it reaches the view it is HTML encoded (i.e. <p> etc...). Here is what the form looks like pre-post:
pre-post http://www.matthewkimber.com/images/so/pre-post.png
And here is what the result is in the div below the "Submit" button:
post result http://www.matthewkimber.com/images/so/posted.png
I've set a breakpoint within Visual Studio and it shows as bare angle brackets (no encoding on HTML elements, just characters).
breakpoint results http://www.matthewkimber.com/images/so/dataInsideTheActionMethod.png
This, of course, is the stripped down test. I've tried encoding it, decoding it both in the view and in the controller to no avail.
By default everything is encoded when you use razor. I think you're looking for the Raw method.
It would also be a good idea to check the response using Fiddler or Firebug.
Try this:
#Html.DisplayTextFor(modelItem => item.Note)
You can also use HtmlString("")

Resources