On a .cshtml page I have a single textbox inside a form. When I enter some text and press return it triggers a POST to a controller of the same name (different signature). The code processes the text and a model is created and passed back to the same page where in addition to the original textbox a grid is now populated (conditionally). Everything works, except the text in the textbox is retained.
This is a little odd, considering that most of the questions on here are about retaining the text after a POST and the indication has been that the text should not automatically be retained.
I can probably assign the textbox an empty string but I am simply wondering if I have this wrong?
Even if it was a simple textbox, html textbox is a input control that has two very important properties, i.e.
name
value
browser will send this name value pair to server
and the default behavior of server is to return the collection of all pairs back to browser when its done whatever it was supposed to do.
this collection is called post data. (or sometimes form data)
Yes, you could clear the textbox in code if everything was fine on postback
If something was wrong (exception or validation) you could do nothing ( as you do now) and text will be there again, what's makes sense in the UI
.
Related
I have a Product edit screen. The user can select a Vendor for the Product. To do this, I display a jQueryUI dialog box which allows them to browse for and select a Vendor. When the user selects the Vendor, I update a hidden VendorID input on the page, which is part of my page's model. I also update several divs with details about the Vendor they have selected. These are for display purposes only--only the id is needed to persist the selected Vendor.
This all works fine and dandy except when there is an error on postback, in which case I redisplay the same view. ModelState takes care of preserving all my form fields (including the hidden VendorID). However, my divs with the Vendor text are (of course) empty since they're not posted to the server.
I first went down the path of creating hidden fields for each of my Vendor display fields and putting them on the model. Then the hidden fields survive the postback, but that doesn't solve the problem of actually redisplaying the text on the screen.
The three options I can think of are:
On postback, if there is an error, go to the database, fetch the Vendor using the supplied VendorID and re-populate the model with the text I want to display.
Use RenderAction and have an action which renders the details of the selected Vendor.
Use readonly textboxes instead of divs to display the Vendor details.
None of these feel very satisfactory to me. I feel like I might be missing an obvious solution. Are there any better solutions?
I would suggest you not have the extra Vendor information come down as part of the main page. Create a javascript function showVendorInfo(). When called, if the VendorID hidden input has a value, it gets the relevant Vendor information via AJAX and displays it, using an AjaxGetVendorInfo action method. Call this function from two places:
In document.ready()
after a Vendor is selected with jQueryUI display.
Now, this would be in an action method. You could, if you expect your users to have latency issues, do the following to avoid some ajax calls: In the view check if you know the VendorID; if so, call Html.RenderAction call the same AjaxGetVendorInfo action method from the view.
A bonus to this is that it avoids what I have found to be a big no-no: Including both display-only values and model-binding values in your ViewModel. This makes for a very confusing ViewModel, especially when there are validation errors. [Getting on soap box] It's best to have your ViewModel to just have properties intended for modelbinding, for your state. Put list values, extra display information, etc., into ViewData or have them show up via AJAX.
I am trying to learn asp.net MVC and having an issue to submit a textbox value to a model.
I have a text box in which users will type a number and when they hit the routelink the routelink will take the value from the textbox and assigns it to one of .Page item.
<%=Html.TextBox("PageIndex")%>
<%=Html.RouteLink("Search", "UpcomingEvent",
New With {.Page = "I want to put value of PageIndex textbox here"})%>
How can I assign the value of the textbox to .Page variable?
Thanks for your time and help!
You can't do that because the RouteLink gets rendered on the server.
If you want to construct a URL based on the user input without a postback, you'll need to do some client-side scripting (ie JavaScript).
It sounds like you're not expecting to post back to the server once they have the textbox value entered. If that is the case then you're going to need to use javascript to change the link's href property. Html.RouteLink is all done server side.
If you are using jquery then it would be something like
$("#pageIndex").change(function()
{
$("#pageLink").href += "?pageIndex=" + $("#pageIndex")"
}
Of course that isn't going to work with multiple change events being fired but that part is left as an exercise for the reader.
I understand that fields such as Html.TextBox() accept two values, the first one being the name and the second one being the value. And so does Html.TextArea(). But in a case where the form is submitted as AJAX and the div where the form is placed is replaced with a view from the server, the form fields insist on taking the previous values. An image is worth a thousand words:
image http://img132.imageshack.us/img132/4171/aspnetmvcbug.png
I've checked everything on the controller and the model and the image is from debugging the view itself. The model is empty but the fields generated from it take the value of the previous submission.
The postback data is held in the ModelState. The built in HtmlHelper methods will look for values stored in the model state based on the name of the form element when rendering their content.
Check the View.ModelState property. Forms can grab values from there in certain circumstances.
Do you have an entry ViewData["Body"]? MVC will also attempt to bind a control to a ViewData item based on the name.
HI,
I'm sure I'm missing something very obvious here so please forgive me.
I'm using MVC 2 Beta and I have a model that has several properties, strings, ints etc. the usual stuff.
It also has a byte array that contains an image.
I have an edit action method on my controller decorated with a [HTTPGet] attribute.
The method passes the model to the view which is a form that has the usual text boxes that bind to the various string properties and an img element that is bound to the byte array/image.
This all works as it should and I see all the data including the image. This is all pretty standard stuff.
But when the user submits the form to my [HTTPPost] version of the action method that accepts the same model as its parameter the image property is null. i.e. the image property does not appear to be part of the model binding.
In the normal course of events we would do some validation and pass the model back to the view to be rendered so the user can see if the edits were successfull or not. But just passing the model back "as is" - the view does not render the image again because its no longer in the model.
I know I can go and get the image again (from the database or where ever) and put it back in the model before passing it to the view, but is that the right stratergy or have I missed something?
Regards,
Simon
How do you render the image that is contained as binary data in model? Do you use classic webforms controls (what would be not recomded in mvc terminology)?
Anyway, if the image is only displayed in the view it is not posted when the user submits the form because only input fields (checkboxes, text fields, hiddens) are submited to the server. image element is not. Remember that in MVC it is simple HTML doing all the work of posting data to the server - there is no viewstate nor automatical postback that will persist the state of the controls.
You have two solutions:
Encode binary data in some hidden field so it would be posted again.
(better) Do not send the image data back and forth between the client and the server, but detect if the user provided new image (i expect you wolud use file input for that) and if the user left the file input empty then update the model with the image already stored in database to display it again. Otherwise update the image in the database.
Anyway, i'm curious how do you display image from binary data in model. I think it would be simpler to create some controller action that would return binary data so you could use URL of that action in src attribute of img tag, or store images as files and use their URL instead of binary data.
I have an application where I need the user to be able to update or delete rows of data from the database. The rows are displayed to the user using a foreach loop in the .aspx file of my view. Each row will have two text fields (txtName, txtDesc), an update button, and a delete button. What I'm not sure of, is how do I have the update button send the message to the controller for which row to update? I can see a couple way of doing this:
Put each row within it's own form tag, then when the update button is clicked, it will submit the values for that row only (there will also be a hidden field with the rowId) and the controller class would take all the post values as parameters to the Update method on the controller.
Somehow, have the button be scripted in a way to send back only the values for that row with a POST to the controller.
Is there a way of doing this? One thing I am concerned about is if each row has different names for it's controls assigned by ASP.NET (txtName1, txtDesc1, txtName2, txtDesc2), then how will their values get mapped to the correct parameters of the Controller method?
You can use multiple forms, and set the action on the form to be like this:
<form method="post" action="/YourController/YourAction/<%=rowId%>">
So you will have YourController/YourAction/1, YourController/YourAction/2 and so on.
There is no need to give different names to the different textboxes, just call them txtName, txtDesc etc (or even better, get rid of those txt prefixes). Since they are in different forms, they won't mix up.
Then on the action you do something like
public ActionResult YourAction(int id, string username, string description)
Where username, description are the same names that you used on the form controls (so they are mapped automatically). The id parameter will be automatically mapped to the number you put on the form action.
You can also have multiple "valid-named" buttons on the form like:
<input type="submit" value="Save" name="btnSave" id="btnSave"/>
<input type="submit" value="Delete" name="btnDelete" id="btnDelete" /
and than check to see what submit you have received. There can be only one submit action sent per form, so it is like all the other submit buttons did not actually existed in the first place:
if ( HttpContext.Request.Form["btnDelete"] != null ) {
//Delete stuff
} elseif ( HttpContext.Request.Form["btnSave"] != null ) {
//Update stuff
}
I also think that you can implement a custom ActionMethodSelectorAttribute like here http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx (also listed above) to have cleaner separated code.
As rodbv said you want to use seperate <form> elements.
When you are using Asp.Net MVC or classic html (php, classic asp, etc) you have to forget the Asp.Net way of handling button presses. When a form is posted back to the webserver all the server knows about is simply "the form was sent, and contained the following input elements".
Asp.net (standard) adds a wrapper round many of the standard html postback actions using javascript (the __doPostback javascript function is used almost everywhere) and this adds information about which input element of the form caused the postback and delivers it to the server in a hidden form variable. You could mimic this behavior if you really so desired, but I would recomend against it.
It may seem strange 'littering' a page with many <form>'s, however it will mean that the postback to the server will be lighter weight and should make everything run that little bit faster for the user.