I am submitting some data in database and after submit I want to show same page. But I am viewing the page the textbox value is not empty.
ModelState.Clear();
I have used to clear the textbox.
But still the textbox value is remain. please suggest me to clear the model after submit in mvc3.
public ActionResult AddNewCategory(CategoryViewModel model) {
if (ModelState.IsValid) {
int result = 0;
var categoryEntity = new Category {
CategoryName = model.CategoryName, CategorySlug = model.CategorySlug
};
result = Convert.ToInt32(_categoryRepository.AddNewCategory(categoryEntity));
if (result > 0) {
ModelState.Clear();
}
}
return View(model);
}
You're getting the same model, because you're passing it to the view View(model). You have couple options here: either pass an empty model, or redirect to the get variant of your post action.
1)
if (ModelState.IsValid)
{
//saving
if (result > 0)
{
ModelState.Clear();
return View(new CategoryViewModel());
}
}
2)
if (ModelState.IsValid)
{
//saving
if (result > 0)
{
return RedirectToAction("AddNewCategory");
}
}
PS: I strongly advice to use the second approach as you might want to make other DB calls to construct your model and you won't want to do this in multiple places.
in very simplest way try it
if(ModelState.IsValid)
{
//code here to save data to database
db.SaveChanges();
ModelState.Clear();
}
return view(new CategoryViewModel());
Hear is what does ModelState.Clear()
ModelState.Clear() is used to clear errors but it is also used to
force the MVC engine to rebuild the model to be passed to your View.
So as in your case #Vsevolod Goloviznin suggested you can use:
return View(new CategoryViewModel());
to have view with empty values
Related
I'm reading Professional ASP.Net MVC 5 and the section on Model Binding shows 3 ways to do the same thing. They are listed below. Can anyone explain the pros and cons of each method?
The first example uses if ModelState.IsValid
the second example uses if TryUpdateModel
The third uses both.
What am I missing here? All seem to work. Why 3 ways to write it?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit (Album album)
{
if (ModelState.IsValid)
{ db.Entry( album). State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction(" Index");
}
return View( album);
}
View( album);
}
[HttpPost]
public ActionResult Edit()
{
var album = new Album();
if (TryUpdateModel( album))
{ db.Entry( album). State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction(" Index");
}
else
{
return View( album);
}
}
[HttpPost]
public ActionResult Edit()
{
var album = new Album();
TryUpdateModel( album);
if (ModelState.IsValid)
{
db.Entry( album). State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction(" Index");
}
else
{
return View( album);
}
}
The first is very simple and supports the most common use where simply newing up the model and mapping the data to it is fine. The instance creation and mapping is handled automatically and "just works".
The third allows you map the incoming data to an existing object instance. If for some reason you already have an object instance you want to map the data too (it probably already has extra data in you want to use and that data doesn't exist in a new instance MVC would automatically create) then this is how you would do it.
The second is the same as the third, but allows you to differentiate between "The model failed to update" and "the model updated, but is invalid".
I am trying to implement Captcha and i have noticed that when the modelstate evaluates to is not valid my page errors out with the message that all my viewbag.items are now null. Any idea how to fix this?
So i have a controller that sends a multiple viewbag items to my view. For example something like this:
public ActionResult Create()
{
...(code shortened)...
var IVariable = from i in db.SomeTable
select i;
foreach (var x in IVariable)
{
BagCategory.Add(x.ArmyCategory);
}
Viewbag.BagCategory = BagCategory
}
The POST method looks something like this:
[HttpPost]
[ValidateAntiForgeryToken]
[CaptchaValidation("CaptchaCode", "SampleCaptcha", "Incorrect CAPTCHA code!")]
public ActionResult Create([Bind(Include="ID,ItemName,Price,ArmyCategory,Race,Company,PictureLink,Notes,EmailAddress")] Sell sell)
{
if (ModelState.IsValid)
{
db.ItemsOffered.Add(sell);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(sell);
}
In my view i run through the items in viewbag.BagCategory but this is now null when captcha is failed and causes the website to explode. What can i do to fix this?
Thank You.
In your post action you have to repopulate Viewbag.BagCategory, because now when the model isn't valid you are returning the view without the viewbag.
{
if (ModelState.IsValid)
{
db.ItemsOffered.Add(sell);
db.SaveChanges();
return RedirectToAction("Index");
}
////REPOULATE THE BagCategory HERE
return View(sell);
}
I was previously doing my views without [HttpPost] in this manner:
public ActionResult Details(string nextButton)
{
if ((nextButton != null) && ModelState.IsValid)
return RedirectToAction("Confirm");
return View(myData);
}
NB: myData is my serialized View Model (which I am not sure if this is the problem).
I also was previously using DataAnnotations on my properties, e.g. [Required]. If any fields in the .cshtml view failed to validate (i.e., no input in a required text box), upon clicking the "nextButton", the user would be presented with the standard client-side validation error (as well as previous items filled in would still be filled in).
If the user corrected the errors and went through to submit the information they could re-visit that page later and it would be blank (i.e., none of their prior inputs would be visible if they submitted).
Now, in order to localize text I've had to move away from DataAnnotations and put validation in my controller temporarily. So I have also started using [HttpPost] thusly:
public ActionResult Details()
{
return View(myData);
}
[HttpPost]
[ActionName("Details")]
public ActionResult DetailsPOST(string nextButton)
{
if (DetailsValidation())
{
if ((nextButton != null) && ModelState.IsValid)
return RedirectToAction("Confirm");
}
return View(myData);
}
...
private bool DetailsValidation()
{
bool validate = true;
if (String.IsNullOrEmpty(myData.FirstName))
{
AddModelError("FirstName", T("Please specify a First Name."));
validate = false;
}
if (!validate)
return false;
if (myData.FirstName.Length > 25)
{
AddModelError("FirstName",
T("First Name cannot be more than 25 letters."));
}
return ModelState.IsValid;
}
The above code works with my validations all the way to submission. However, the problem now is if the user returns to the Details view the data they entered populates the text boxes, whereas with the original way (no [HttpPost] or special validation) if the user went back to the Details view they would be presented with a fresh page (none of their data in the text boxes).
Sorry if this isn't clear. But is there a way to have the text boxes clear after submission, so if the user goes back its a fresh page? Or is this just something I have to deal with given the new way I am doing things.
Thanks.
UPDATE How I created myData in the Controller:
private MyViewModel myData;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var serialized = Request.Form["myData"];
if (serialized != null) //Form was posted containing serialized data
{
myData = (MyViewModel)new MvcSerializer()
.Deserialize(serialized, SerializationMode.Signed);
TryUpdateModel(myUsData);
}
else
myData = (MyViewModel)TempData["myData"] ?? new MyViewModel();
TempData.Keep();
}
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Result is RedirectToRouteResult)
TempData["myData"] = myData;
}
I use this for a wizard, to pass data to a subsequent view (Details > Confirm > Submit).
How did you initialize myData in this action method? Did you populate it with the data from the database?
public ActionResult Details()
{
return View(myData);
}
If so, you could initialize an empty myData and pass it to your view:
public ActionResult Details()
{
var myData = new UserData();
return View(myData);
}
No real resolution on this issue, so it seems I just have to accept this behavior.
I am not sure if I am overlooking something obvious.
Once I do a POST, I have the following (Note: What I am trying to do is to default the same view with some null values so the user can create another entry):
[HttpPost]
public ActionResult QkInsert(ProgInfo model)
{
if (ModelState.IsValid)
{
ProgService.InsertQuickEntry(model);
model.Name = null;
model.Address = null;
model.Phone = null;
return view(model);
}
return view(model);
What is strange is that when I look at the value of model in the IsValid()
return view(model)
I do see the null values.
But when it is shown on the view, it is not null. It is basically the same view as when I had entered the data the first time. Any idea? Have I overlooked something?
Also notice how I have done return view(model) twice. Is there any other way of doing this to where I do it only once and not repeat?
That's because HTML helpers are first looking into the ModelState when binding their values and only after that the value in your model. This is by design.
So if you want to change any value of the model inside a POST action you need to remove it from the ModelState first:
[HttpPost]
public ActionResult QkInsert(ProgInfo model)
{
if (ModelState.IsValid)
{
ProgService.InsertQuickEntry(model);
ModelState.Remove("Name");
ModelState.Remove("Address");
ModelState.Remove("Phone");
model.Name = null;
model.Address = null;
model.Phone = null;
return view(model);
}
....
}
Now the view will render the modified values.
If the model is not valid you will return the same model, your second return.
There is no need at all for the first return view(model) as there is no code between it and the second one, so it will call anyway. That is, delete the first return and the logic is identical.
this is my first mvc 3 project, i am using linq to sql.
public ActionResult Edit(int ID)
{
try
{
Tutorial tut = reposi.Tutorials.Single(d => d.TutorialID == ID);
return View(tut);
}
catch
{
return RedirectToAction("List");
}
}
[HttpPost]
public ActionResult Edit(Tutorial tut)
{
if (ModelState.IsValid)
{
//tut.TutorialID = ID;
tut.EditDate = DateTime.Now;
tutContext.SubmitChanges();
return RedirectToAction("List");
}
else
{
return View(tut);
}
}
after I click on the "Edit" button, It takes me back to list page, and changes are not saved. still old values.
You need to first get the Tutorial from your database, then make the changes, then SubmitChanges().
[HttpPost]
public ActionResult Edit(Tutorial tut)
{
if (ModelState.IsValid)
{
Tutorial t = tutContext.get(tut.Id);
//tut.TutorialID = ID;
t.EditDate = DateTime.Now;
tutContext.SubmitChanges();
return RedirectToAction("List");
}
else
{
return View(tut);
}
}
Note, your tutContext.get(tut.Id); may be different depending on your implementation.
tut.EditDate = DateTime.Now;
tutContext.SubmitChanges();
return RedirectToAction("List");
Your tutorial object is not managed by db context yet. so the context didn't save the object change when you change the tut object and invoke tutContext.SubmitChanges().
First thing first, you must lookup the tutorial object from the context.
Tutorial tut = ctx.Tutorials.Single(d => d.TutorialID == ID);
after you get the tuts object form the tuts context, that tuts object is managed by the db context. then you can modify the tut object and submit the changes.
Tutorial tut = ctx.Tutorials.Single(d => d.TutorialID == tut.ID);
tut.EditDate = DateTime.Now;
ctx.SubmitChanges();
You need this in the [HttpPost]
When you debug, are you reaching the Post action in the controller? Make sure your form action is set to POST instead of GET.