How to Integrate Enterprise Library Validation Application Block ValidationResults between WCF and ASP.NET? - asp.net

Enterprise Library Validation Application Block (VAB) integrates with ASP.NET and also with WCF.
Is there a way to integrate ValidationResults created in WCF with ASP.NET?
e.g. an ASP.NET web page invokes a WCF service. The WCF service validates the data using VAB and returns validation information via a FaultContract. The ASP.NET page can take the results and display some error messages. However, a common approach is to indicate which fields have errors (e.g. inline message or asterisk). It seems that most of these approaches will involve being able to correlate the validation result with a control or with a validator.
I don't think there is an out of the box solution but was also curious if anyone had done this and what their approach was.

Since there is no out of the box solution and there aren't any answers posted, I will share what I implemented. I'm not in love with the approach but it is working for me.
Overview
The basic approach is for the ASP.NET page to populate a mapping between properties on the DataContract objects to the ClientId of the control that is being validated. When a validation error occurs the ClientId is returned back from the service to the asp.net page as part of a FaultContract. Then the details from the FaultException are extracted; the ASP.NET page retrieves the ClientId of the control that caused the error and appropriate action can be taken (e.g. change control look and feel or set the text on a validator).
Details
All of the DataContract objects inherit from a base class that exposes a Dictionary. This dictionary is used to map object properties to ASP.NET controls. In the Dictionary, the key is the property name on the DataContract object and the value is the ClientId of the control. Before invoking a service, the client must attach the Dictionary to the DataContract object.
When a ValidationResult is created by Enterprise Library it contains a property called Target which is the object that was validated. ValidationResult also contains a property called key which is the name of the property from the target object that was validated. The ValidationResult key is also a key into the Dictionary that was set in the ASP.NET page before calling the service.
With the ValidationResult key, the ASP.NET supplied information (ClientId) can be extracted from the ValidationResult Target. The information is then added as the Tag of the ValidationResult. Unfortunately, Tag is a readonly property so it has to be set by creating a new ValidationResult and passing the tag to the constructor.
The collection of ValidationResults is then transformed to a pre-existing CustomValidationResults collection (which looks just like ValidationResult) that we needed to use. The CustomValidationResults are then added to a custom ValidationFault and a FaultException is thrown.
The ValidationFaults are then extracted from the FaultException in the ASP.NET page. The ValidationFault contains the ClientId of the control which is associated with the error so the page can choose to display the Messages as it sees fit.

Related

Check if curent user has access to specified MVC path

I need to extend asp:Menu to support linking to MVC routes (my project has a mix of MVC and non-MVC pages). My menu is generated using a custom class which determines if a user should be shown a node based on their priveleges to the file it referes to.
MVC pages are restricted using the AuthorizeAttribute. Avoiding mocking (if possible) I want to
Determine if the path refers to an MVC page or a standard page
If MVC, determine if the user has the rights to access it
Here's my method signature inside the menu generation class:
Private Function CanAccessPage(path As String) As Boolean
Here's the algorithm I used for this,
Based on #SLaks answer here, I was able to determine if the path referred to an MVC route.
If it was MVC, I grabbed the controller type (this required knowing what namespace my controller's were in)
Got the action method by controllerType.GetMethods(actionMethodName) (if you have multiple methods with the same name, you must pick the one your link refers to. Probably the one with an HttpGet attribute).
Used actionMethodInfo.GetCustomAttributes(GetType(AuthorizationAttribute), False) to get a collection of all authorization filters for the specified action
Called OnAuthorization with the fake context info I build in step 1 for each attribute.
Check if TypeOf filterContext.Result Is HttpUnauthorizedResult and return accordingly

DataContract IsReference=true returning empty objects

I have a WCF service with cyclic references that I was using the CyclicReferencesAwareAttribute attribute (http://chabster.blogspot.com/2008/02/wcf-cyclic-references-support.html) to solve. However now I want to use the same service with a Silverlight client. Receiving data works well on the Silverlight client with this method, however the CyclicReferencesAwareAttribute attribute does not work on the Silverlight side when I want to send objects back again.
I have changed to use the IsReference property on the data contract which is supposed to get round with this issue. However now the objects that are returned are empty! (All fields are either default or null). This is the same in my ASP.NET client (original) and my Silverlight client.
Has anyone hit is issue before? Here is the attribute.
[System.Runtime.Serialization.DataContract(Namespace="http://testnamespace.co.uk/entities", IsReference=true)]
1- Make sure that all the properties have the System.Runtime.Serialization.DataMember attribute.
2- Make sure that all properties that need to be transfered have a public getter and setter

Calling cached data (in service layer) from an ASP.NET MVC View - what other alternative do we have?

We are adding tooltips to our ASP.NET MVC product, and we are getting the text from our database (technically, from a cached copy of the data). To do so, we created an Html Helper method:
<%=Html.Tooltip(Model.GetTooltipText(Tooltips.ClientPage.StartDateId))%>
The GetTooltipText method is in our BaseViewModel, and simply uses the passed in Id to fetch the tooltip from cache.
Would this be considered a bad design? What other alternatives would we have?
Thanks!
Its probably a better idea to grab all the Tooltip's in one hit and put them in some sort of strongly-typed collection (perhaps a Dictionary<id,string>), cache all of that in your service layer.
Then you could put this in a ViewModel and pass it through to your strongly-typed view.
In your View you could simply access that strongly-typed collected via the Model based on the unique key?
I.e.
<%: Model.Tooltips[SomeDateId] %>

When calling ScriptManager.RegisterStartupScript, what is the point of the 'Type' parameter?

A minor question that I hope admits of a simple answer that I'll kick myself for not noticing.
So, when we have the following overload of RegisterStartupScript
public static void RegisterStartupScript(
Control control,
Type type,
string key,
string script,
bool addScriptTags
)
we have to provide a type as well as a control. Now, I can see what the point of specifying the control - the script gets pushed out just in case the control is part of the partial page render. But what is the point of the Type parameter? Usually one just sets it to the type of the control. And this is in fact the suggestion made by MSDN:
control
Type: System.Web.UI..::.Control
The control that is registering the client script block.
type
Type: System..::.Type
The type of the client script block. This parameter is usually specified by using the typeof operator (C#) or the GetType operator (Visual Basic) to retrieve the type of the control that is registering the script.
So why do we have to specify it? Presumably not just to spare the .Net Framework the bother of retrieving the runtime type itself.
Usually type is the type of the page or control that registers a script. This is just a way to prevent that two different controls register different scripts using the same key.
Excerpt from MSDN:
A client script is uniquely identified
by its key and its type. Scripts with
the same key and type are considered
duplicates. Only one script with a
given type and key pair can be
registered with the page. Attempting
to register a script that is already
registered does not create a duplicate
of the script.

Is ASP.NET MVC 1 forwards compatible with ASP.NET MVC 2?

Can I run a MVC 1 application using the MVC 2 assemblies without a hitch? I understand that some 3rd party tools have had stuff broken in MVC 2, but let's assume I'm not using those any other tools.
There have been breaking changes.
If you want a 1.0 project to run on 2.0, it does look for things in different places; so you'd have to migrate the application to 2.0..
Here are the changes that could possibly 'break' (current as of Preview 2):
Changes in Preview 2
Helpers now return an MvcHtmlString object
In order to take advantage of the new HTML-encoding expression syntax in ASP.NET 4, the return type of the HTML helpers is now MvcHtmlString instead of a string. Note that if you use ASP.NET MVC 2 and the new helpers with ASP.NET 3.5, you will not be able to take advantage of the HTML-encoding syntax; the new syntax is available only when you run ASP.NET MVC 2 on ASP.NET 4.
JsonResult now responds only to HTTP POST requests
In order to mitigate JSON hijacking attacks that have the potential for information disclosure, by default, the JsonResult class now responds only to HTTP POST requests. AJAX GET calls to action methods that return a JsonResult object should be changed to use POST instead. If necessary, you can override this behavior by setting the new JsonRequestBehavior property of JsonResult. For more information about the potential exploit, see the blog post JSON Hijacking on Phil Haack’s blog.
Model and ModelType property setters on ModelBindingContext are obsolete
A new settable ModelMetadata property has been added to the ModelBindingContext class. The new property encapsulates both the Model and the ModelType properties. Although the Model and ModelType properties are obsolete, for backward compatibility the property getters still work; they delegate to the ModelMetadata property to retrieve the value.
Changes in Preview 1
DefaultControllerFactory class changes break custom controller factories that derive from it
This change affects custom controller factories that derive from DefaultControllerFactory . The DefaultControllerFactory class was fixed by removing the RequestContext property and instead passing the request context instance to the protected virtual methods GetControllerInstance and GetControllerType.
Custom controller factories are often used to provide dependency injection for ASP.NET MVC applications.
To update the custom controller factories to support ASP.NET MVC 2, change the method signature or signatures to match the new signatures, and use the request context parameter instead of the property.
“Area” is a now a reserved route-value key
The string “area” in Route values now has special meaning in ASP.NET MVC, in the same way that “controller” and “action” do. One implication is that if HTML helpers are supplied with a route-value dictionary containing “area”, the helpers will no longer append “area” in the query string.
If you are using the Areas feature, make sure to not use {area} as part of your route URL.
Known Issues
The Add View dialog box throws a NullReferenceException when the Create strongly-typed view check box is checked, a View Content selection other than “Empty” is selected, and a View data class type name is specified for a type that does exist. When specifying a type name, either use the drop-down list to select the type name or type the fully-qualified type name. For types that do not exist, you must set View Content to “Empty”.
Check out this document. You'll learn about the breaking changes :
http://go.microsoft.com/fwlink/?LinkID=157072
One gotcha that has bitten me is that all the fields of a model are now always validated on a post.
The changes is described by Brad Wilson here.
Steve Anderson's blog post describes the issue and my favorite solution (using a custom validator).

Resources