I am new to MVC, so please bear with me.
We have a large WebForms website, where content is managed by a
custom CMS. I have added DataAnnotation attributes to my model
properties. The attributes have an ErrorMessage property, but this
must be a compile-time constant.
I would like to get error message texts at runtime from out custom
CMS. We already do this in our WebForms pages, so the infrustructure
is in place i.e. manager classes with aproprate methods for retrieving
the correct texts by key.
My question is where do I hook in at runtime in order to populate the
texts from the CMS to be displayed when validation error occur
client-side or server-side?
One way I guess would be to create your own DataAnnotationsModelMetadataProvider. Derive from this class and override the CreateMetadata method. Don't forget to register your custom MetaDataProvider with the ModelMetadataProviders when your WebApp initializes.
Related
I am currently working on multiple ASP.NET MVC web apps.
All of these web apps have the same navigation bars/menus.
Some of the menu items are app specific, so they can be passed from the respective app.
Some of the menu items are not app-specific, such as whether user is admin or not, based on which I show an admin link on the nav bar. The logic for getting the admin property is available in the business layer.
Is it possible to make this html helper such that I don't have to pass the non-app specific parameters from the respective apps ?
Can I call the business layer from the html helper ?
Is it advisable ?
I want this html helper or any other solution easily distributable...
Thanks
HTML helpers are extension methods on the System.Web.Mvc.HtmlHelper type that return an System.Web.Mvc.MvcHtmlString object. If you want "easily distributable", then you can create a library project with the helper extensions that you need. Then add the project in as a reference on the MVC project.
#using statements can bring in the extensions to the Razor view. The helper object that you bring in through the extension method in the library will give you access to most of the information available to the Razor view at the time the helper is called (with the ViewContext property).
The extensions can be overloaded as much as needed to account for variations in the projects. Common menu options can be added to the library as a static collection that can be accessed by both the MVC project and the extension methods.
update
MVC is set up such that you can do what you want. You have a lot of control. Your helper can include as much code as you need. It's not like you are "breaking the rules". But best practice dictates that you keep your business logic in the controller. By putting that into the helper, which gets called by the Razor view, you are in effect moving the business logic into the Razor view.
HTML Helpers in general are a lightweight way to create HTML code. Thus they are easy to reuse any you can have dozens or hundreds on a single Razor view. That idea gets broken when you move a bunch of business logic into the helper. Then you have a potential of slowing things down if the helper is to be reused a lot.
Good rule of thumb for MVC, if your helper starts getting complicated, create a partial view. I would probably create a model to represent the menu, then create a partial view in the Shared folder that uses that model, then call it from the parent view. I think that would give you more flexibility, and be more in keeping with the MVC best practices.
I have just noticed that DataTypeAttribute class is inherited from System.ComponentModel.DataAnnotations.ValidationAttribute.
In terms of ASP.NET MVC DefaultModelBinder class, is DataTypeAttribute is a validation attribute? In plain English, does ModelBinder validate the object according to DataTypeAttribute?
For example, if I specify DataType property to DataType.EmailAddress, will it validate the e-mail address or this attribute is only providing metadata for objects.
UPDATE
I found a similar question on SO :
Is the DataTypeAttribute validation working in MVC2?
So, according to that it is not working as a validation attribute. So, why it is inherited from System.ComponentModel.DataAnnotations.ValidationAttribute if it is not serving as a validation attribute?
DataTypeAttribute does not contain any validation logic itself.
The reason it derives from ValidationAttribute is so that you could create a new custom data type class, which was both a DataType and a Validation, all wrapped up into one. It's an unfortunate side-effect of .NET not allowing multiple inheritance.
So, yes, it's a validator... that does no validation by default. It's waiting patiently for you to do the heavy lifting. :)
Actually, if you look inside of MVC 3 Futures, you'll see that we leveraged this to create new custom validators where we knew that jQuery was already capable of providing client-side validation logic, and we added mirrored server-side validation logic (and preserved the DataType benefits for templating).
Based on the MVC3 source code the only purpose of the DataTypeAttribute is to populate the ModelMetadata.DataTypeName property .And this property is only used by the EditorFor/DisplayFor template generation. So you were right it has nothing to do with validation. So I don't know why is it inherited from ValidationAttribute. Maybe the framework authors reserved it for future use.
I want DefaultModelBinder not to perform any validation based on DataAnnotations metadata. I'm already using DataAnnotations with DynamicData for the admin area of my site, and I need a different set of validation rules for the MVC based front-end.
I'm decorating my classes with the MetadataType attribute. If I could have different MetadataType classes for the same model but used on different scenarios that would be great. If not I'm fine with just disabling the validation on the DefaultModelBinder, either by setting some property or by creating a specialized version of it.
Take a look at ModelValidatorProviders.Providers collection and leave only necessary entries.
ModelValidatorProviders.Providers.Clear() should propably solve your problem, but you should still look at it to see how it works.
First post so please be gentle :)
When creating user controls in ASP.NET MVC, what is the best way to structure the code so that the controllers that invoke views that use the user controls do not all have to know so much about the controls? I would like to know a good way to maintain DRY while using user controls in ASP.NET MVC.
Please note, this question only pertain to user controls that require special handling and logic on a postback. I have no problem creating nice DRY code for user controls that are either view only (using RenderPartial) or that require some pre-processing to create the appropriate ViewModel (using RenderAction).
Also, this question pertains only to achieving reusable controls within an application. I am not worried about reusability between applications at this point.
To give a specific example, let's say I would like to create a 'Quick Add' user control which contains three entry fields, First Name, Last Name and Company Name and a submit button. When the QuickAdd functionality is used, the following steps should be performed independent of what page the control is on:
Validate that the fields were not empty, if they are, show an indicator.
Perform a lookup to a repository to see if the Company already exists, if not; create it.
Create a new contact associated to either the existing company or the newly created company
Re-render the existing page. If no validation errors, the user would see the exact same page again, otherwise the same page with validation errors.
My main problem with achieving DRY has to do with all the controllers that invoke views that contain the partial view end up having to have an Action Method to process the form submission from the Quick Add. Even if I break out the logic for processing the information into a separate controller and invoke that method from each of the other controllers it seems like a burden that each and every controller that invoke views that have reusable controls have to have that knowledge.
The other option I looked at was to have the reusable control always submit to a specific action method / controller but then there is no way for that controller to know how to re-populate the model appropriately for the specific controller that invoked the view that contained the reusable control (in step 4).
I am aware that there is talk of subcontrollers in MVC 2 (from this question ASP.NET MVC - Contained User Controls) but since it is not there yet, what is the best way to structure the code to achieve maximum reusability while maintaining DRY?
Is there an alternative to having to have all the controllers that invoke views that use a reusable control (with the characteristics of the one described above), having to have an Action Method to process the information from the control?
At the end of your post, you ask "Is there an alternative to having to have all the controllers... having to have an Action Method to process the information from the control"
The answer for that question is to write a custom model binder. Your custom model binder can be responsible for the populating the values from the incoming form control(s) into model or properties used by all of the controllers. Normally, you want to separate the validation from the model binding, but there is no reason that you couldn't combine them as well.
I highly recommend 6 Tips for ASP.NET MVC Model Binding for a deeper discussion of the topic along with some good references.
I'm not sure why you say the Quick Add form has to have an action method in each controller that uses it; if you wrap the Quick add functionality in a Html.BeginForm(); Html.EndForm() combo, you can have the beginform method specify the name of the action and controller, so you only need one controller.
I understand where you are coming from; it's something I have been thinking about to. While I don't know all the answers, I have some ideas for you to consider. Every controller action method is invoked via a ControllerActionInvoker class, which you can customize. This class handles invoking all of the action methods, so here you could embed certain aspects of reusable code across all or certain action methods.
Look into filters too, as there are a variety of filters that you can use or customize that fire for action methods that implement it. This way, code can run before and after the action method execution and result execution.
For validation, there is already validation components built in that will prevent page submission... you could also consider XVAL which has some other nice features. The Unity framework is an IOC container framework, which dynamic injection keeps things loosely coupled and DRY, as you can inject all kinds of references.
Also, you mentioned subcontrollers; the MVC preview has additional features you may be interested in... for instance, it has a RenderAction method that can render an action method within another action's view.
Hopefully that helps... so what am I missing?
Have a look at RenderAction and RenderPartial. Those are the canonical ways to arbitrarily inject a common control into a view.
Use RenderPartial when you want to include the data as part of your ViewData infrastructure.
Use RenderAction when you want the data to be separate from the ViewData infrastructure. The data will come from the controller method you specify in RenderAction.
Check out the NerdDinner tutorials, if you haven't done so already.
I am working on an ASP.NET MVC application that contains a header and menu on each page. The menu and header are dynamic. In other words, the menu items and header information are determined at runtime.
My initial thought is to build a base Controller from which all other controllers derive. In the base controller, I will obtain the menu and header data and insert the required information into the ViewData. Finally, I will use a ViewUserControl to display the header and menu through a master page template.
So, I'm trying to determine the best practice for building such functionality. Also, if this is the recommended approach, which method should I override (I'm guessing Execute) when obtaining the data for insertion into the ViewData.
I'm sure this is a common scenario, so any advice/best-practices would be appreciated! Thanks in advance!
EDIT:
I did find the following resources after posting this (of course), but any additional anecdotes would be awesome!
http://www.singingeels.com/Blogs/Nullable/2008/08/14/How_to_Handle_Side_Content_in_ASPNET_MVC.aspx
How do you use usercontrols in asp.net mvc that display an "island" of data?
Depends on where your information is coming from. We have standard view data that we use to generate some of the information we have on screen that we create in just this fashion. It works well and is easily maintained. We override the View method to implement strongly typed view names and use this information to retrieve some of the data that the master page requires as well.
You could write a helper extension to render the header/menu
That way you could have it show in different places in the view should you need to, but only one place for maintenance.
public static HtmlString MainMenu(this HtmlHelper helper)
Use a base controller class to implement generell filter methods. The controller class implements some filter interfaces IActionFilter, IAuthorizationFilter, IExceptionFilter and IResultFilter which are usefull to implement some common behavior for all controllers.
If the menu data is the same on all pages but different for each unique user.
Generate the menudata in an OnAuthorization or Initialize method of your controller base class. First will be called on authorization. Initialize will be called before every action method. You have access to ViewData Context. Generate the menudata there.
Put the view content for menu and header into the master page and access generated ViewData there.
I tackled a similar design challenge a couple months ago - implementing a breadcrumb feature that changes as user navigates from page to page.
I overrided the OnActionExecuting method to gather the breadcrumbs and store them in ViewData (I use the name of the action as the breadCrumb of the view). Then I updated the Master page to include a user control that takes the ViewData and renders the breadcrumbs.
One thing to be aware is that if you were using the default ASP.NET MVC error handling attribute [HandleError] and your error page is using the same Master page that attempts to read the ViewData, you will soon find out that you can't access ViewData from your error page and it will raise an exception. Depending on whether you need the ViewData for failure scenarios, the viable solution is to use a separate Master page or do this: How do I pass ViewData to a HandleError View?
I'll answer your question with another question. Will the base controller have to determine what type it really is in order to generate the proper menu data? If so, then you're defeating the purpose of polymorphism and the code to generate the data should go in each controller, perhaps in OnActionExecuting if the menu is the same for all actions. Pushing it back down into a parent class seems likely to end up with some switch statement in the parent class doing what each derived controller really ought to take care of.