Is it possible to get standard ASP.NET MVC Unobtrusive Validation to work in Orchard CMS? - asp.net-mvc-3

I'm trying to build a custom module to integrate with Orchard CMS to implement a business application. While Orchard CMS is an MVC application, it doesn't seem possible (or, at least easy) to do all the things that can be done "out of the box" with MVC.
I'm trying to get unobtrusive validation to work on my view but can't seem to get this to work.
Update: As per Rohan West's advice below, I've now got the scripts included in the page using the ResourceManifest class and the Script.Require calls.
However, the validation attributes on the actual HTML elements are not being generated despite having the .NET attributes on my properties for which I'm using #Html.EditorFor on.
I have set the appSettings in the web.config file as follows:
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
<add key="webpages:Enabled" value="false" />
<add key="log4net.Config" value="Config\log4net.config" />
</appSettings>
Still no joy!
Update 2: As per Rohan West's suggestion, modifying the OrchardStarter class to comment out the following lines "solves" the problem:
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider());
There should be a better way of handling this though.

You need to define the script in the resource manifest for your module.
public class ResourceManifest : IResourceManifestProvider
{
public void BuildManifests(ResourceManifestBuilder builder)
{
var manifest = builder.Add();
manifest.DefineScript("jQueryValidation").SetUrl("jquery.validate.js", "jquery.validate.min.js").SetVersion("1.7").SetDependencies("jQuery");
manifest.DefineScript("jQueryValidation_Unobtrusive").SetUrl("jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js").SetDependencies("jQuery", "jQueryValidation");
}
}
and then in your page
#{
this.Script.Require("jQueryValidation_Unobtrusive").AtHead();
}
Have a look at the following class
Orchard.Environment.OrchardStarter
In Orchard 1.4.2 there is a line which removes all ModelValidatorProviders
ModelValidatorProviders.Providers.Clear();
This is removing the default DataAnnotationsModelValidatorProvider from the collection.
You could try adding it to the collection,

Related

Enabling CORS through Web.config vs WebApiConfig and Controller attributes

There seems to be two functionally different ways to enable cross-origin request sharing in Web API 2.
One is to import System.Web.Http.Cors, decorate a controller with the EnableCors attribute and to write config.EnableCors() in the WebApiConfig:
[EnableCors(origins: "http://111.111.111.111", headers: "*", methods: "*")]
public class GenericController : ApiController
{
// etc.
The other is to modify the Web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://111.111.111.111" />
<add name="Access-Control-Allow-Methods" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
Is there a functional difference between these two different approaches? Which one is correct - don't these accomplish the same thing? If both methods are used to enable CORS, will things blow up?
If you add the headers to the web.config, every request that is served by that application will include the specified headers. This method is supported at the web server level and doesn't depend on config.EnableCors() being executed. You can use that method to add any HTTP header you want.
On the flip side, the EnableCors attribute requires WebAPI and you need to add some code to make it work. To the end user, the result is the same.
As for which way is better? I've liked keeping those settings in the application code by using the attribute so these settings are obvious to future developers. Depending on your needs, you may want to look into a abstract CorsApiController which your main ApiControllers could inherit to deliver the same CORS headers over and over. But this method won't work if the CORS headers need to vary from controller to controller or from action to action.

Trying to enable client side validation in Orchard

I am trying to get client side validation enabled in Orchard for the comments. I have followed the advice in this SO discussion. I have commented out:
//ModelValidatorProviders.Providers.Clear();
//ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider());
I have included the following in Resource Manifest in the Comments Module.
manifest.DefineScript("jQueryValidation").SetUrl("jquery.validate.js", "jquery.validate.min.js").SetVersion("1.7").SetDependencies("jQuery");
manifest.DefineScript("jQueryValidation_Unobtrusive").SetUrl("jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js").SetDependencies("jQuery", "jQueryValidation");
I stuck the following inthe view:
this.Script.Require("jQueryValidation_Unobtrusive").AtHead();
Also I added DataAnnotation to the CommentPartRecord.cs file, decorating Author with [Required]
And the changes to the Web.config:
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
And despite all of this server side valdiation for the Comments is whjat works. There is no client side validation.
The DataAnnotation should'nt be on CommentPartRecord but on CommentPart.
But Orchard.Comments is not a good example because CommentPart doesn't define the same properties than the Record (it will be refactored in a future version).
Try this on another module o one that you create.

Showing built-in Error View for MVC 3

I followed this tutorial, but I am still receiving the ASP.NET screen that says to turn on Errors do this, or to show custom error page do this.
I have registered the HandleErrorAttribute and added the <customErrors mode="On" /> in web.config. The attribute is sitting directly on the line before the Controller class signature.
Am I still missing something?
EDIT
I removed the attribute from the class as you suggested, and this was the result. Nothing special going on I don't think.
web.config
</appSettings>
<system.web>
<customErrors mode="On" />
<compilation debug="true" targetFramework="4.0">
<assemblies>
Global.asax
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Error*
Server Error in '/' Application.
Runtime Error
Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed.
Details: To enable the details of this specific error message to be viewable on the local server machine, please create a <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "RemoteOnly". To enable the details to be viewable on remote machines, please set "mode" to "Off".
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="RemoteOnly"/>
</system.web>
</configuration>
Notes: The current error page you are seeing can be replaced by a custom error page by modifying the "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="mycustompage.htm"/>
</system.web>
</configuration>
If you wish to see a custom error page (one that you design yourself) then you need to actually create the page and refer to in in the customErrors element;
<customErrors defaultRedirect="GenericError.htm" mode="On" />
In the example above, you would create the GernericError.htm page in your web application. This will be displayed if there is an error.
If you want to see details about the actual exception being thrown, then you need to set the mode to mode="Off" or mode="RemoteOnly"
Also, make sure that you are running the right version of asp.net (i.e. asp.net 4.0) in IIS for your application, otherwise your web.config file may not be parsed correctly, leading to this page.
Here is a conversation about Razor custom-views that works for me and many others. Test it. May be helpful to you too.

What is the best way to inject configuration settings into Javascript in an MVC app?

What is the best way to inject configuration settings into Javascript in an MVC app?
I've seen how it is done using ASP.NET webforms, but not sure how to do this with MVC.
#using System.Configuration
...
var checkTimer = #ConfigurationManager.AppSettings["CheckTimer"];
In Web.config:
<appSettings>
<!-- Polling timer to check for alerts -->
<add key="CheckTimer" value="10000"/>
</appSettings>
But in my rendered output I just get the following:
var checkTimer = ;
var checkTimer = #Html.Raw(Json.Encode(ConfigurationManager.AppSettings["CheckTimer"]));
Check out the Javascript serializer:
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
If it is not too fancy , you can have a hidden variable and then access it in javascript.

Set connectionstring for Membership Service via code

I have an ASP.NET web project and a membership provider configured via my web.config. Its fully working so no problem there.
We have an older system with a lot of users and I would therefor like to create a class library that can create users in this ASP.NET project but since its a class library it cannot have its own app.config-file.
is it possible to set all this information via code somehow?
<membership defaultProvider="ShidMembershipProvider">
<providers>
<clear/>
<add name="ShidMembershipProvider" type="SundaHus.AspNet.Membership.ShidMembershipProvider" connectionStringName="ShidConnectionString" enablePasswordRetrieval="true" enablePasswordReset="true" requiersQuestionAndAnswer="true" applicationName="ECB3-development" minRequiredPasswordLength="5"/>
</providers>
</membership>
You have a custom membership provider it looks like? This connects to your own custom database? You should be able to just point to that database for your code. Or, if you just inherit the functionality from the base class, you can also try overriding the Initialize method, look for the connection string, and change the value to something else.

Resources