I am currently working on a project in MVC 3 where I am leveraging Entity Framework to persist one data model over two Views which each contain one HTML Form (similar to wizard-based design).
Yet after the user fills out the appropriate fields on the first View and submits the form, client-side validation for the entire model is triggered, and validation errors are shown for fields that will not even be available for input until the second View instantiates.
I have currently implemented a workaround where I simply turn off client-side validation for the first View entirely, but I am certainly not keen on the idea of populating my model with data that has not been validated at all. This is bad. M'kay.
Is there any way to partially validate the fields on the first View and not trigger valdiation for the whole data model?
That's where ViewModels comes. Instead of directly binding the domain model with the views, you should create view models over them and bind to the views.
If you are not required to put validation on the EF models directly then you can use the MetadataType to do partial validation as needed. Take a look at my long example here on stackoverflow.
Thanks for the input all. However, I was able to obtain a solution in a very simple way. By placing the following code in the HttpPost element of the first View...
if (ModelState.IsValidField("FirstField") && ModelState.IsValidField("SecondField"))
return RedirectToAction ("NameOfAction", model);
else
return View();
...I was able to achieve partial field validation. However, this field-specific approach will ONLY work provided the Submit button on the first View has class "cancel" and the additional validation errors that are generated (for the fields that are NOT present on the first View) are manually cleared before the above if statement. To do this, use:
ModelState["FieldName"].Errors.Clear();
No major change in architecure. No partial Views. No handing off unvalidated Data.
Works very well...
NOTE: If the second View loads with validation errors, use:
ModelState.Clear();
in the Action where the second View is initially called. This will make the second View load clean and error free, while still showing the validation errors later upon final form submission.
Related
In cases where new items need to be added to a list via ajax, what is the biggest benefit of using something like Knockout.
So far what I have been doing is, on my view, use an editortemplate (with asscociated viewmodels) to render a list of items. Then to add a new item, I make a request to an action that loads a server-side viewmodel, and returns an EditorTemplte object which just gets appended to the list. Like this:
return Json(new { this.RenderPartialViewToString("MyEditorTemplate", model) });
The knockout way of doing things requires the implementation of another view model to display items, and then another template to display it. But doing it this way requires duplication of code since the view model has to be represented in 2 places: in the cserver side code and then the view for the knockout viewmodel. Isn't that bad practice?
Am I missing something, or understanding the purpose of knockout and MVVM?
The biggest benefit that you will see from Knockout is that you will not need to hit the server in order to add a new item to your list - everything happens client side. This has multiple benefits including:
You reduce load on your server.
You improve the end-user's experience.
You can keep multiple elements on the page up-to-date with your model without any server interactions.
Two great examples of this can be found at these Knockout tutorials:
Working with Lists and Collections
Loading and Saving Data
As far as duplicating code, if you take a look at those two tutorials, you'll notice that you don't need to duplicate code. For example:
Create a view to display your entire list.
To add a new item to the list, create a partial view that you load when you add a new item to the page - that partial view is bound to Knockout
When you submit the entire form, everything in that list will be submitted - including those items you added via Knockout.
Your ViewModel will be specific to your list item (you don't need to create an entire ViewModel for everything, necessarily). And your view is specific to a single list item.
Hope that's clear. Knockout is pretty straightforward and they have some great documentation and tutorials to help you move forward.
IMHO, the following is cleanest option for the architecture of knockout and asp mvc mixed together.
Have your ASP.net acting as a webservice and have knockout control all your view templating and logic.
Otherwise, yes there will be potential replication of viewmodels and having to refactor both front and backend code when you need to change your model.
I have a form that only has a checkbox. If the checkbox is not checked then the page won't be valid and won't submit the data. On the view I have out putted some fields from the model object, just to let the user know what they are deleting. When I click the Submit button and the model state is not valid the page will show the validation error but the data from the model is no longer there!
Does anyone know how I can persist this data without making another call to the database to populate the model object?
Thanks
ASP.Net MVC will not magically persist model info.
You need to either include it in hidden fields in the form (which an attacker can modify), or re-fetch it from the database.
If you don't repopulate the Model from the DB, you have to postback all the data, using hidden fields for example.
Anyway, I don't understand how the model validation could fail, being just a checkbox :/.
I'm trying to use a html.dropDownList helper with a strongly typed view model with ajax. I can't the post the code because of the nature of the project.
Here basically what I'm doing...
loading a mvc view via a strongly type view model
clicking a button which does an ajax post to a controller method
using the TryUpdateModel to parse the view model
processing the request
rendering a parital view for the ajax request
According to the article listed below, the problem is that "ASP.NET MVC assumes that if you’re rendering a View in response to an HTTP POST, and you’re using the Html Helpers, then you are most likely to be 'redisplaying a form' that has failed validation."
http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx
Instead of "redisplaying the same form value", I need the html.dropDownList to be set to the same value in the view model.
Does anyone know of any custom dropDownList helpers or have any ideas of how to achieve this?
Things I've already tried/considered
per the blog, manually removing the modelstate item...didn't work - didn't pick up the value in the view model - just defaulted to the first item in dropdown list
considered just writing a regular select list...but this is sloppy and cumbersome since I'm rending multiple select lists in a loop
writing my own custom dropDownList helper...wanted to avoid reinventing the wheel
Thanks in advance
Its not fully clear to me what your problem exactly is, but I've had a similar problem. I used the Html.DropDownListFor(, SelectListItem[]) helper. At postback it sets the value to the choosen one. Your postback view doesn't require to have all the fields of the original model.
#Html.DropDownListFor(model => model.SelectedValue, MyModels.DropDownSelectables());
Here I want the selected value as the model.SelectedValue variable and within my (seperate) model I made a array of selectlistitems. The rest is automagic.
Hope it helps, D
I am buiding a UI screen for editing the details of an Ecommerce Order. The model for my view (OrderModel) has everything I need (in properties that are also ViewModels), but the UI isn't designed to be able to edit all of it at once.
For example, one part of the UI is for customer data..another for order details, and another for tracking information, each having their own "Save" buttons.
I realize that I could use one giant form and use hidden form fields to populate the non-editable fields, making each "Save" button post all the data, but that smells bad.
I'd like to segment the editable chunks into smaller ViewModels that are posted and validated individually while retaining the strong typing but I'm unsure of how to achieve this in MVC3. Will I need partial views that are called from the primary view?
FYI, I'm using ASP.NET MVC 3 with Razor syntax and client side FluentValidation.
Partial Views are a good solution. You can pass different ViewModels to each partial view. But if only sections of the overall view are updated at a time I would not do a post back on the whole page. Instead I would use Ajax calls using JQuery/Javascript to update the individual information back to the controller. I would also look into something like Knockout.js to handle the data binding on the page.
I'm coming from a WebForms environment. When I wanted values from a radiobutton, the form simply got ajax reposted or I got it thru javascript.
I've searched the web, but can't seem to find an equivalent for MVC 3 Razor.
I'm not posting the form, so I can't use the FormCollection object in the ActionResult.
I simply want to get the value of which option in the RadioButton is checked when a user checks one of them.
I assume I would do this thru an Action method in a Controller once a user checks one of the values.
Note also, that this radiobutton list is in a partial view and is available to the entire website (because it is in my _Layout.cshtml view).
Can someone please help me out with what I think should be a simple task?
You need to use javascript. See this post. MVC does not have the concept of an Auto-Postback like in Webforms. This is an optimization in the page loading time (no self-managed viewstate). This means you need to manage the statefulness of controls yourself.
In short, if you're not posting (or "getting") the form then the value won't be available in the controller...more specifically, neither the controller nor it's actions will be called at all.
If you're trying to do something strictly UI related, then you may want to consider jQuery.
If you're trying to do some sort of model validation inside of the view, you may want to reconsider your approach and usage of the MVC pattern.