MVC :: Custom Model Validation Against Collection Of Instances?
Jul 22, 2010
i am creating a MVC2 application for pubs and bars. I have a model 'Opening_Time' with the following properties:
int Day,time OpeningTimetime ClosingTimeWhen adding/editing an Opening_Time, I want to validate an Opening_Time, to check the user isn't adding one for an existing Day (ie they can't have two entries for the same day).
How/Where is the best place to do this?
Preferably, I want to do it a Model level, so I can use Model.IsValid and the Html.Form helpers
This project I'm working on have this custom clientside JavaScript validation framework created for (which I cannot change) that show error messages/summary based on your data annotations and a "Validate" method in your ViewModel.
Like I said I'm not allowed to change this, so wont be able to go with suggestions doing that.
What the person that created this did not foresee, is that one might need put several partials of the same type and having the same view model (each in a form) on a view.
So I went ahead and did things the normal way (using Html.whateverFor<model => model.whatever) and wala!....the custom validation thing throws error messages for the specific form fields, next to each form in the view. I was suggested to create a "prefix" for each instance of the view model, and do something like this:
What I'm trying to do is rather basic, but I might have my facts mixed up. I have a details page that has a custom class as it's Model. The custom class uses 2 custom objects with yet another custom object a property of one of the 2. The details page outputs a fair amount of information, but allows the user to post a comment. When the user clicks the post button, the page gets posted to a Details action that looks something like this:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Details(VideoDetailModel vidAndComment) { ....} [Code]....
The only fields on the form that is posted are CommentText and VideoId. Here is what the VideoDetailModel looks like.
public class VideoDetailModel { public VideoDetailModel() { [Code].... I suppose if I added more form fields for the properties I need, they would get posted, but I only need 1 form entry field for the CommentText. If I could get the same Model objects value that were sent to the page to post with the page, it looks like the solution is rather simple. I think using the RenderPartial in the middle of a form is problematic somehow to how the form gets written in html. I can't really put my finger on why things went bonkers, but if I do my RenderPartials before my form and then begin my form with the text entry field and the hidden VideoId, the default ModelBinder works just fine. I was beginning the form, writing the hidden VideoId, rendering several partial views, create my CommentText field, and then closed the form out. The CommentText field would get bound just fine. The hidden VideoId would not. Maybe I missed a rule somewhere about using RenderPartial.
For completeness, the partial view I was rendering took a Comment object and just wrote out it's CommentText data. Several of these objects would exist for a single Video object. All of this data was in a custom type and passed into the View (the main view) as it's Model. This partial view did not have a form and did not have any data entry fields.
I am a MVC newbie & am lost in various ways validation can be implemented in my application.
I created a custom model-level data annotation validator attribute, but am unable to display its error message in the view. Basically, I have let's say 5 properties in the Entity class Job (model-level custom attribute called UniqueKeywords defined on it):
1) LoginID: value comes in the URL
2) Title: Required property level attribute defined on it
3) CatID1, CatID2, CatID3 - 3 categoryIDs - these are dropdowns in the view with same list of keywords in all 3.
I want to mandate that the values picked by the user in all 3 category dropdowns should be different.
With reference to the code pasted below, here is the explanation of what happens:
When I submit the form without specifying a title or picking anything from any of the 3 category dropdowns, the validation occurs for the property level Required attribute as well as model level uniquekeywords attribute, but the error is displayed only next to the required field "Title". I can confirm that the custom validation also works by filling in some text in the Title field & then re-posting the form...this re-displays the view, but the error message "Category cannot be duplicated" is not displayed.
I have the current block of code inside an OnPreRender method of a validator that is inheriting from BaseValidator. If I have one instance of the validator this works fine, but if there are multiple instances the javascript flakes out. As it stands the acutal evaluation function has to be rendered on a per instance basis. I know it's kind of a drop in the bucket, but I'd like to register the block below just once instead of giving each instance a unique key to register with.
I need to bind a bunch of properties over my model entities. All of them uses the List<T> class. I already managed to write a model binder that can treat individualy types derived from that class, but i can't set the value of this property on the model. every time i check the model afer the bind process i see a list with 0 itens.
Here's how it runs.
After i post the values the model binder catchs up the types for bindingAt the custom model binder i check if this property is a List<T> typeIf it is then i perform the bind like it have to be, if not i let the default binder do the job.Finally i return the object binded. What happens next is the issue i've mentioned "i see a list with 0 itens" on the Model property.
I have been trying to design a form, which uses a view model that contains an object array. I want to set up this form so that when the submit button is clicked, all the members of the array are updated. Here is my code:
The class definition of the array element:
[Code]....
The problem is that when I clicked the submit button, none of the luSubject objects in the array Subjects got updated. But if I set up some initial values for the members of the luSubject objects, for instance, set the Name field to be "Maths" in the constructor of luSubject class, then it got displayed on the text box when the form page was loaded. This suggests that this form could display the data in the array, but cannot update it.
This is part of a larger problem which has plagued me for a while now (see "EntityCollection already initialized" error with entity as model in Asp.Net MVC? for the entire picture).
But I found a web site with someone who had faced a similar problem and apparently solved it for his needs [URL]. I tried it, but had to make some modifications to fit my code, and the helper methods supplied by a tutorial by Steven Sanderson (see previous post).
I'm very close it seems, but not quite:
UpdateModel(consultant, "Consultant"); if (vm.Programs != null) //Unnecessary? Can it even be null if it's initialized from the model? for (int i = 0; i < vm.Programs.Count; i++) { Program formProgram = vm.Programs[i]; Program modelProgram = consultant.Programs.SingleOrDefault(x => x.Id == formProgram.Id); if (modelProgram == null) _repository.AddProgram(formProgram); else modelProgram = formProgram; UpdateModel(modelProgram); //Doesn't work. The modelProgram object does get updated with the correct property values, but it isn't saved to the repository... } _repository.Save();
Although this follows the example on the site above, and the modelProgram does get updated with the changed properties, these values are not saved to the database on _repository.Save() on the Consultant object, even though the modelProgram object is a reference to a Program object on the Consultant... What am I doing wrong?
I am using the Entity Framework by the way, if it isn't clear.
(BTW, if anyone has any input on the previous question and the whole picture, that would be welcome too, it is still unresolved).
UPDATE: There was apparently a mistake in here: UpdateModel didn't actually do any updating, I had just referenced a different object (the one in the viewmodel) for the modelProgram, so of course it had the right property values. I still want ideas for how to achieve this though...
I have recently started working on ASP.NET with MVC 2 framework, and I am facing following difficulty in validating my data,
Scenario:
In my application the view (ASPX) is divided into tabs (jQuery) and each tab's content is ViewUserControl (ASCX). The main model for the view has collection of sub models for individual tabs. I use RenderPartial method to render view user control.
[Code]....
And the user control (Tab1.ascx) refers the specific model for it,
[Code]....
Now if in my Tab1Model if I put following validation
[Code]....
In the controller ModelState.IsValid is always indicates TRUE. How do I override the validation behavior such that it as well looks the items in the collection member (which holds sub models) as well.
Note: I'm working with MVC3 RC and Razor views.I've got this model:
[Code]....
I want to have a strongly typed create view for this model, that allows you to insert 1 to many addresses and phone numbers as part of the view. Ideally, the Action is strongly typed as well:
[Code]....
What would this view look like to facilitate creating 1 to many Addresses and PhoneNumbers, as well as having the state re-created correctly if the ModelState fails when posting? I've tried a number of variations including EditorTemplates and can't figure out how to do this.
i am just having a play with HtmlHelpers in MVC, very useful stuff and now i am trying to create one for dropdowns based on passing in a model ( any ) what the property is for the value and same for text.
I've been trying to get a custom validator component working that ensures at least one checkbox from a checkboxlist has been checked. I've been used some code I found on dotnetjunkies.com but the client-side validation didn't work. I've been attempting to modify it to get the client-side javascript validation to work with no luck. Basically, I compile the below code into a DLL and add it to my bin folder.
I am using ASP.net to retrieve data from a Lotus notes DB using OLEDB connection. I use a ADOrecordset to read the values. When I open the ADo connection, I would like to store each record being read in a custom object and thereby create a collection of custom objects as ADO connection times out when kept open for long.
I then need to iterate throught the collection of custom objects to retrieve the values.
In any event I override I don't have any attributes in my "base.Attributes or this.Attributes" collection. How's that possible? The rendered output clearly shows an id and an href attribute.
I'm trying to get rid of the href part and put in my own. Unfortunately Attributes.Remove("href") won't work.. because there's no such attribute. Or any attribute for that matter.
I'm writing a custom ASP.NET webcontrol and would like it to have a collection of custom items which can also be specified in the XML markup. Something like this:
class MyControl: WebControl { public IList<MyItemType> MyItems { get; private set; } }
How do I do this? I though this was all about implementing some interface on the collection or adding some special attributes to the property, but nothing I do seems to work.
My MVC 2 app includes a simple file upload within in a strongly typed view and I am trying to figure out how to apply model validation to the file name. Is this possible? Is there better way to do file upload within an MVC app?
The salient parts of the (prototype) controller code are:
[Code]....
The Create view code was generated with VS2010 and then modified to support file upload and client side validation:
I have a viewmodel with a property of a model class type. I set some properties in the model class to be able to show it to the user but then when I make a post, the model gets validated. How to overcome this? I don't want to enforce the DataAnnotations contraint in this case....
public class TheViewModel { TheModel TheModel { get; set;} } [code]...