I have a form in my MVC application that has a textbox. When the form is POSTed to the page, I make a modification to the model value and redisplay the view. The textbox still shows the value that was POSTed though.
Here is the code:
#using( Html.BeginForm() ) {
#Html.TextBoxFor( m => m.Foo )
<input type="submit" value="Save" />
}
public class TestController : Controller {
public ActionResult Index() {
return View();
}
[HttpPost]
public ActionResult Index(MyModel model) {
model.Foo += "bar";
return View(model);
}
}
Whatever is in the form (lets say I type in foo) I add "bar" and try to show the form again. But when the form is redisplayed all I see is foo. I remember reading something about why this is happening but can't seem to find it now. I know this is a poor example but I'm just trying to remember why it is doing this, and what the workaround is (other than redirecting). Is there a way to have it show the updated model value and not what the form value that was posted?
You can clear the model state and the helper should display the new value.
[HttpPost]
public ActionResult Index(MyModel model) {
model.Foo += "bar";
ModelState.Clear();
return View(model);
}
Related
This question already has answers here:
View not updating after post
(3 answers)
Closed 4 years ago.
I am doing something fundamentally wrong. I have created a simple example of my problem.
I have a simple class as follows:
public class Example
{
public string Text { get; set; }
}
I have created two methods on my controller
This is the view page you hit. It creates a new Example object.
public ActionResult Example()
{
var model = new Example {
Text = "test"
};
return View(model);
}
Then the post back when the form is submitted
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
model.Text += "a";
return View(model);
}
The view is as follows:
#model Stackoverflow.Example
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>#Model.Text</h1>
#Html.EditorFor(model => model.Text);
<input type="submit" value="Save" />
}
When I first visit the page the heading and the text box have the same value
I press submit and the page loads again. The title has updated but the text box has the same value.
Why is the #Html.EditorFor(model => model.Text); not getting the updated value?
When you post a model back to an ActionResult and return the same View, the values for the model objects are contained in the ModelState. The ModelState is what contains information about valid/invalid fields as well as the actual POSTed values. If you want to update a model value, you can do one of the following two things:
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
ModelState.Clear();
model.Text += "a";
return View(model);
}
or
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
var newValue = model.Text += "a";
ModelState["Text"].Value = new ValueProviderResult(newValue,newValue, CultureInfo.CurrentCulture)
return View(model);
}
You need to clear the model state on post method of controller
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
ModelState.Clear();
model.Text += "a";
return View(model);
}
I know there are a lot of questions about this, but not in a single one I've seen (and I've been searching for two hours now), did I see what to write in the razor view (.cshtml file) to fire the controller method associated with saving the model object to the database, or how that object is passed.
So I want to make a simple registration page. I created the Users model, created the view associated with the model, named Register.cshtml, and I access the view through the Account controller which has a Register method:
public ActionResult Register()
{
return View();
}
The tutorial I follow uses the default code generated in the View when you create it for the Users model.
<input type="submit" value="Create" class="btn btn-default" />
And states that you should make a method in the Account Controller as follows:
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}
(where DatabaseEntities is the name of my database)
This doesn't work, because, on running the application, it says that it doesn't know which one of the two methods to fire.
System.Web.Mvc.ActionResult Register() on type Biblioteca.Controllers.AccountController
System.Web.Mvc.ActionResult Register(Biblioteca.Models.User) on type Biblioteca.Controllers.AccountController
This is the error I get.
I thought of renaming the second method RegisterPost(User obj), but then I don't know how to call the method with the argument, because in the razor view, I don't know which is the object that gets created on submitting the form.
I could use an #Html.ActionLink(), but I don't know how to send the object.
I actually tried adding an onclick method to the submit button, as follows:
onclick="location.href='#Url.Action("RegisterPost", "Account")'"
But after filling the form and clicking the submit button, nothing happens. Nothing gets inserted into the database.
I don't know what to do now. Please help.
Add attribute [HttpGet] to the first action and [HttpPost] to the second action:
[HttpGet]
public ActionResult Register()
{
return View();
}
[HttpPost]
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}
You can read more on MSDN
To expand a bit, try adding [HttpPost] above the second Action method.
[HttpPost]
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}
I'm trying to create contact us page where user fill's in the detail and submit and at the bottom display message which comes from server.
The way i have implemented is something like this.
[HttpGet]
public ActionResult ContactUs()
{
//Process the stuff
return View("~Views/Contact/Contact.cshtml", model)
}
now when page load it hits above method and display form with the layout including header and footer.
Once user submits form it hits below method
[HttpPost]
public ActionResult ContactUs(ContactUs form)
{
//Process the stuff
View.Message="Thank you for your enquiry."
return View("~Views/Contact/Contact.cshtml", model)
}
It returns to the same page but it doesnt render the body layout not even header or footer simply display outputs form.
Not sure what im doing wrong there, is there any better approach ?
Thanks
Based on the code above, I believe you're attempting something like:
public class UxController : Controller
{
public ActionResult WithResponse(ActionResult result, string message)
{
PageResponse(message);
return result;
}
protected void PageResponse(string message)
{
TempData["Ux_Response"] = message;
}
}
That would be your Controller, then the Controller for that specific page, it would look like:
public class HomeController : UxController
{
public ActionResult Index()
{
return View();
}
public ActionResult SubmitForm(string message)
{
return WithResponse(RedirectToAction("Index"), "Thank you for feedback.");
}
}
Then in your front-end code, you would do the following:
#if(TempData["Ux_Response"] != null)
{
<div>#TempData["Ux_Response"]</div>
}
<form action="/Home/SubmitForm" method="post">
<input type="text" name="message" />
<input type="submit" value="Submit" />
</form>
Obviously you could enhance this, with more versatility. However, you're relying on Post, which will cause a screen flicker. So the better route, may be to do Ajax, then return a JsonResult. Hopefully this helps you out.
It should work if you change your controller/view like this.
Controller;
public ActionResult Contact(ContactModel model)
{
ViewBag.Message = "Your contact page.";
return View(model);
}
public ActionResult SaveContact(ContactModel model)
{
//process values in your model and then rest model
ContactModel.Message = "Thank you for contacting us"; //show thank you message
return RedirectToAction("Contact",model);
}
View;
#model MvcApplication1.Models.ContactModel
#{
ViewBag.Title = "Contact";
}
#using (Html.BeginForm("SaveContact", "Home", Model, FormMethod.Post))
{
#Html.DisplayFor(m => m.Message);
<button type="submit">Submit</button>
}
I manged to solve this. the issue was the because i was using sitecore cms the form action wasnt processing it full work flow, after i removed the action, it defaults to action method which defined in cms and triggers the cms workflow.
I am trying to return a different view from my controller. However, although the correct view is displayed the URL stays same.
This is my form in /Company/Create view.
#using (Html.BeginForm("Create", "Company", FormMethod.Post))
{
// Form here
}
So basically, the form and model is submitted to /Company/Create action. If the submitted model is valid, then I process the data and redirect to /Company/Index view with
return View("Index");
As I said, correct view is displayed however, URL (address bar) is still http://.../Company/Create
I tried RedirectToAction("Index"); It does not work also. And I do not think its a good MVC practice. I have a single layout and Company views are rendered with RenderBody()
Any ideas ?
Thanks.
Edit :
This is my action method,
[HttpPost]
public ActionResult Create(CompanyCreate model)
{
/* Fill model with countries again */
model.FillCountries();
if (ModelState.IsValid)
{
/* Save it to database */
unitOfWork.CompanyRepository.InsertCompany(model.Company);
unitOfWork.Save();
RedirectToAction("Index");
return View();
}
// If we got this far, something failed, redisplay form
return View(model);
}
You need to redirect to another action if you want the url changed.
However RedirectToAction doesn't redirect instantly but returns aRedirectToRouteResult object which is an ActionResult object.
So you just need to return the result of RedirectToAction from your action:
[HttpPost]
public ActionResult Create(CompanyCreate model)
{
/* Fill model with countries again */
model.FillCountries();
if (ModelState.IsValid)
{
/* Save it to database */
unitOfWork.CompanyRepository.InsertCompany(model.Company);
unitOfWork.Save();
return RedirectToAction("Index");
}
// If we got this far, something failed, redisplay form
return View(model);
}
I am new to Asp.net MVC and have no idea as to how can i perform the search. Here's my requirement, please tell me how will you handle this :-
I need to have textbox where user can enter a search query or string. The user then clicks on a button or presses enter to submit it. The string needs to matched with a table's property name.
NOTE:- Querying the data and fetching the result isn't the main point here. All I need to know is how will you take the user input and pass it to a controller action or whatever for further processing. Just tell me how will you read the user input and where will you send it to search.
Asp.Net MVC uses standard HTTP verbs. For the html part, it's a normal html form that points to an url. Server side, that url will be routed to a controller/action which will handle the input and do what is needed.
Let's have a sample. You want to make a search form. First of all, it's a best practice to have search forms use the HTTP GET method instead of POST, so the search results can be bookmarked, linked, indexed, etc. I won't be using Html.BeginForm helper method to make things more clear.
<form method="get" action="#Url.Action("MyAction", "MyController")">
<label for="search">Search</label>
<input type="text" name="search" id="search" />
<button type="submit">Perform search</button>
</form>
That's all the html you need. Now you'll have a controller called "MyController" and the method will be something like this:
[HttpGet]
public ActionResult MyAction(string search)
{
//do whatever you need with the parameter,
//like using it as parameter in Linq to Entities or Linq to Sql, etc.
//Suppose your search result will be put in variable "result".
ViewData.Model = result;
return View();
}
Now the view called "MyAction" will be rendered, and the Model of that view will be your "result". Then you'll display it as you wish.
As always in an ASP.NET MVC application you start by defining a view model which will express the structure and requirements of your view. So far you have talked about a form containing a search input:
public class SearchViewModel
{
[DisplayName("search query *")]
[Required]
public string Query { get; set; }
}
then you write a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SearchViewModel());
}
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
if (!ModelState.IsValid)
{
// There was a validation error => redisplay the view so
// that the user can fix it
return View(model);
}
// At this stage we know that the model is valid. The model.Query
// property will contain whatever value the user entered in the input
// So here you could search your datastore and return the results
// You haven't explained under what form you need the results so
// depending on that you could add other property to the view model
// which will store those results and populate it here
return View(model);
}
}
and finally a view:
#model SearchViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.Query)
#Html.EditorFor(x => x.Query)
#Html.ValidationMessageFor(x => x.Query)
<button type="submit">Search</button>
}
This is the best way to do it.
Create a ViewModel
public class SearchViewModel
{
public string Query { get; set; }
}
Create a Controller
public class SearchController : Controller
{
[HttpPost]
public ActionResult Search(SearchViewModel model)
{
// perform search based on model.Query
// return a View with your Data.
}
}
Create the View
// in your view
#using (Html.BeginForm("Search", "SearchController"))
{
#Html.TextBox("Query")
<input type="submit" value="search" />
}
hope this helps