how to change the themes in asp.net mvc 2 - asp.net-mvc-2

I would like to have an option wherein a user can choose his theme for the site from the dropdown list and the theme applies to that page [atleast].
I want this to be done in ASP.NET MVC 2 without using jquery like frameworks.
How can this be accomplished.
I am using the default webforms viewengine and donot want to go for a custom viewengine for this purpose.

It seems this is not supported out of the box, but here's what I did to implement theming:
First, I Added the App_Themes folder to my project, and set up a couple of themes
I then decided to try and mimic the Web-forms profile provider as close as possible, and added a profile-property to web.config:
<profile>
<properties>
<add name="ThemePreference" type="string" defaultValue="Blue" />
</properties>
</profile>
So, basically what I wanted to do was to be able to load the different css's from the appropriate theme-folder when the theme changed. I did this by implementing a helper method attached to the UrlHelper class so that I could write:
<link href="#Url.Theme("~/Content/Site.css")" rel="stylesheet" type="text/css" />
This should then load the appropriate themed Site.css, and fall back to ~/Content/Site.css if no file was found.
The helper is pretty simple:
public static class UrlHelpers
{
public static string Theme(this UrlHelper url, string u)
{
if (u.StartsWith("~")) u = u.TrimStart('~');
SettingsProperty settingsProperty = ProfileBase.Properties["ThemePreference"];
return url.Content("~/App_Themes/"+settingsProperty.DefaultValue + u);
}
}
Now, in this version of the code it simply gets the default-value, so you'll need to tweak the code slightly. But as you can see, this is not limited to css-files, but works with everything from .master files to images.
Update - Using Session instead of profile
public static class UrlHelpers
{
public static string Theme(this UrlHelper url, string u)
{
if (u.StartsWith("~")) u = u.TrimStart('~');
object currentThemeName = null;
if (url.RequestContext.HttpContext.Session != null)
{
currentThemeName = url.RequestContext.HttpContext.Session["ThemePreference"];
}
return currentThemeName != null ? url.Content(String.Format("~/App_Themes/{0}{1}", currentThemeName, u)) : url.Content("~"+u);
}
}
The return-line in this method checks if it found a ThemePreference session-value, and then returnes the appropriate URL for the content requested, otherwise it simply returns the content as it was requested with no App_Theme prefix.
In your controlleraction for the DropDown postmethod, you'd simply do:
Session.Add("ThemePreference", whateverValueYouGotFromDropdown);
Update ends
With some tweaking and fixing, this should do the trick.
Hope it helps some, even though it's not a complete walkthrough :)

Related

Show warning when EL not found

I'm creating a JSF Applikation and i would like to get some kind of warning (preferably i the console) if i make typos in my EL-Expression.
Example:
On my page i wanted to show some Text that is localized. The locale-config in faces-config.xml is properly set up and works with the var 'msgs'.
I used this code on my page:
<h:outputText value="#{msg.title_edit_customer}"/>
When i checked my Page in the browser, nothing got showed.
I took me a while to realize that i made a typo - with #{msgs.... it worked as expected.
Can i activate some kind of Debug-Output, so i can see directly that there is an invalid EL somewhere?
My Setup: Eclipse 4.4.2, Tomcat 8, MyFaces 2.2.8
Thanks to #SJuan76 i could figure it out:
Create your own javax.el.ELResolver, all the Methods can return null/false.
Open the Source of the Class org.apache.myfaces.el.unified.resolver.ScopedAttributeResolver and copy the methods facesContext(ELContext) and findScopedMap(FacesContext, Object) (since ScopedAttributeResolver is final, we can't extend it).
Edit the getValue-Method:
#Override
public Object getValue(ELContext context, Object base, Object property) {
if(!context.isPropertyResolved()){
//Douple Check false-positives
boolean foundInScope = false;
final Map<String, Object> scopedMap = findScopedMap(
facesContext(context), property);
if (scopedMap != null) {
Object object = scopedMap.get(property);
if (object != null) {
foundInScope = true;
}
}
if (!foundInScope) {
log.warn(String.format("EL-Property %s couldn't be resolved",
property));
}
}
return null;
}
Edit faces-config.xml to register your resolver:
<application>
<el-resolver>com.myPackage.DebugELResolver</el-resolver>
</application>
Since there are many Resolvers and each one does a little bit of the Resolving, our new Resolver should come last. Add following to web.xml:
<context-param>
<param-name>org.apache.myfaces.EL_RESOLVER_COMPARATOR</param-name>
<param-value>org.apache.myfaces.el.unified.CustomLastELResolverComparator</param-value>
</context-param>
Now you'll get some log-Output, every time an expression couldn't be resolved:
03.07.2015 07:34:21 com.myPackage.DebugELResolver [http-nio-8080-exec-2] WARN EL-Property msgx couldn't be resolved
I couldn't figure out how to get the actual EL-Expression (e.g. #{msgx.title_edit_customer}.

Implement validator in Eclipse

I am trying to implement validation in Eclipse. My work has many little projects that serve to customize our product for various customers. Since there are a ton of developers we are trying to find a way to enforce various standards and best practices.
For example, we have many XML configurations that we want to validate. The built-in validators ensure files are well-formed and follow a schema, but we would like to add validations such as checking that a Java class referenced in XML actually exists on the classpath. Another example is validating that a Java class implementing a certain interface does not have any object variables (i.e. the code needs to operate only on parameters and not maintain state).
It appears that there are two ways to add validation. The first is through a builder which adds markers. The second is through stand-alone validation. However, we are not actually building anything, and I have not found any useful tutorials or examples on validation (does not help that help.eclipse.org is currently being moved and is unavailable).
When I right-click a test project and select "validate" I get a message stating there was an error during validation, and my test message does not show up in the problem view. However, there are no errors in the Eclipse log. The host Eclipse shows nothing in the console. No exceptions logged anywhere, and no message. The project does have the required custom nature.
I was following these instructions but there is no code or fully functioning example, and Google has not been kind enough to fill in the blanks. Combined with the Eclipse help site being down right now, I am at a loss as to how to proceed.
plugin.xml:
<plugin>
<extension name="My Validator" point="org.eclipse.wst.validation.validator"
id="com.mycompany.pluginname.validator.MyValidator">
<validator>
<projectNature id="com.mycompany.pluginname.nature.MyNature"/>
<helper class="org.eclipse.wst.validation.internal.operations.WorkbenchContext"/>
<markerId markerIdValue="com.mycompany.pluginname.validator.DefaultMarker"/>
<run class="com.mycompany.pluginname.validation.validator.MyValidator"/>
<runStrategy project="true"/>
</validator>
</extension>
<extension point="org.eclipse.core.resources.markers" name="My Validator"
id="com.mycompany.pluginname.validator.DefaultMarker">
<super type="org.eclipse.core.resources.problemmarker"/>
<persistent value="true"/>
<attribute name="owner"/>
<attribute name="validationSeverity"/>
<attribute name="targetObject"/>
<attribute name="groupName"/>
<attribute name="messageId"/>
</extension>
</plugin>
Validator code:
package com.mycompany.pluginname.validation.validator;
import org.eclipse.core.resources.IProject;
import org.eclipse.wst.validation.internal.core.Message;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
import org.eclipse.wst.validation.internal.provisional.core.*;
import com.mycompany.pluginname.validation.plugin.ValidationPlugin;
#SuppressWarnings("restriction")
public class MyValidator
implements IValidator {
#Override
public void cleanup(IReporter argReporter) {
argReporter.removeAllMessages(this);
}
#Override
public void validate(IValidationContext argContext, IReporter argReporter)
throws ValidationException {
String bundle = ValidationPlugin.getDefault().getTranslationsBundleName();
IProject prj = ((IWorkbenchContext) argContext).getProject();
String[] attributes =
new String[] {"owner", "validationSeverity", "targetObject", "groupName", "messageId"};
IMessage msg = new Message(bundle, IMessage.HIGH_SEVERITY, "test", attributes, prj);
argReporter.addMessage(this, msg);
}
}
I also find it odd that adding validation would require using restricted packages and interfaces. It also seems odd that it wants an IMessage rather than an IMarker.
I did look at Eclipse plugin with custom validation which seems to be oriented around creating a new editor, where I want to validate files regardless of the editor used (in fact I do not want to create an editor).
Edit: I updated to use the V2 framework, but nothing appears in the problem view. What am I doing wrong? Is there a tutorial somewhere that explains how this works? I was able to figure out the following, but obviously it is not correct:
public ValidationResult validate(ValidationEvent argEvent, ValidationState argState,
IProgressMonitor argMonitor) {
final IResource resource = argEvent.getResource();
final ValidationResult result = new ValidationResult();
try {
List<String> contents = Resources.readFile((IFile) resource);
for (int i = 0; i < contents.size(); ++i) {
int offset = contents.get(i).indexOf("bad_string");
if (offset >= 0) {
result.add(ValidatorMessage.create("Found bad string", resource));
result.incrementError(1);
}
}
}
catch (Exception ex) {
result.add(ValidatorMessage.create(ex.getMessage(), resource));
}
return result;
}
I admit this is a stab in the dark: the documentation is not very descriptive and I have not found any tutorials on this V2 validator. Oh, I have a filter on this validator so it only receives specific XML files, which is why there is no input validation.
Also, since I am a pedant myself, I am using the old-style for loop there because I expect to show the line number with the error to the user. But obviously I am not quite there yet.
Another edit: here is the working code. The only issue is the squiggly is not on the correct line because the offset is from the start of the file, not the line. But it does work:
public ValidationResult validate(ValidationEvent argEvent, ValidationState argState,
IProgressMonitor argMonitor) {
final IResource resource = argEvent.getResource();
final ValidationResult result = new ValidationResult();
try {
List<String> contents = Resources.readFile((IFile) resource);
int location = 0;
for (int i = 0; i < contents.size(); ++i) {
int offset = contents.get(i).indexOf(CONSTANT);
if (offset >= 0) {
ValidatorMessage vm = ValidatorMessage.create("Message", resource);
vm.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
vm.setAttribute(IMarker.SOURCE_ID, IMarker.PROBLEM);
vm.setAttribute(IMarker.LINE_NUMBER, i + 1);
vm.setAttribute(IMarker.CHAR_START, location + offset);
vm.setAttribute(IMarker.CHAR_END, location + offset + CONSTANT.length());
result.add(vm);
}
// TODO: account for different line endings.
location += (line.length() + 2);
}
}
catch (Exception ex) {
ValidationPlugin.getDefault().warn(ex);
result.add(ValidatorMessage.create(ex.toString(), resource));
}
return result;
}
Plugin.xml:
<extension name="My Validator" point="org.eclipse.wst.validation.validatorV2"
id="com.company.plugin.validation.validator.MyValidator">
<validator class="com.company.plugin.validation.validator.MyValidator">
<include>
<rules>
<file type="file" name="FileName.xml"/>
</rules>
</include>
</validator>
</extension>
I actually found another SO question along these lines that corroborates what I found: Setting IMarker.CHAR_START and IMarker.CHAR_END attributes for IMarkers Annotations
sigh that document is very out of date. You should use the org.eclipse.wst.validation.validatorV2 extension point, extending the newer org.eclipse.wst.validation.AbstractValidator class.

NLog config file to get configuration setting values from a web.config

Is there a method to get a value from the <ApplicationSettings> section of a web.config within NLog layout variables?
I already store SMTP details within my web.config and don't want to duplicate the settings just to use within my NLog.config.
Ideally I'd like to do something like: ${aspnet-config:SmtpHostServer}
which then fetches the value from the web.config
I couldn't see any obvious way to do this other than creating my own LayoutRenderer (see below). If you're putting into your own assembly don't forget to add the following into your NLog.Config:
<extensions>
<add assembly="YOURASSEMBLYNAMEHERE" />
</extensions>
Hope this helps someone else:
[LayoutRenderer("aspnet-config")]
public class AspNetConfigValueLayoutRenderer : LayoutRenderer
{
[DefaultParameter]
public string Variable
{
get;
set;
}
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
if (this.Variable == null)
{
return;
}
HttpContext context = HttpContext.Current;
if (context == null)
{
return;
}
builder.Append(Convert.ToString(System.Configuration.ConfigurationManager.AppSettings[this.Variable], CultureInfo.InvariantCulture));
}
}
Updated Answer
NLog ver. 4.6 includes ${appsetting:SmtpHostServer} in the core NLog-nuget-package. No longer requires NLog.Extended. See also https://github.com/nlog/NLog/wiki/AppSetting-Layout-Renderer
NLog.Extensions.Logging ver. 1.4 includes ${configsetting} that allows one to read settings from appsettings.json. See also https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer
Original Answer
Nowadays this is possible without custom code:
Use NLog.Extended and use
${appsetting:SmtpHostServer}.
See docs for ${appsetting}
Please note: this isn't supported in .NET Core / .NET standard yet.

Applet on Browser

How I can use some functions that were declared on the applet class? i.e.
this is my class
public class hi extends JApplet{
public void HiThere(){
System.out.println("Hi on Java Console");
}
}
and on my browser it's declared something like:
<applet.... name="HI" id="HI" ......>Ooops!!!</applet>"
but when I tried to use the function there was a mistake, so how a can use the functions declared on my applet class?? Thanks!!!
First you should do this change to your code:
public class HI extends JApplet {
public HI() {System.out.println("Hi on Java Console");}
}
When you have done that, and your browser still has an error, then post the exact error message here. Also you might want to look for a tutorial "programming Java applets getting started", since your code tells me, that you don't seem to know what you are doing.
In order to call your class methods from js you must declare the <object> in html specifying a .jar or .class with your compiled content, the package of the main class and some other parameters like in the follow example (object is for IE, and embed is for FF):
I suppose that you want to invoke the hi.HiThere() method as defined in your question.
<object
width="100" height="100" id="hi">
<param name = "code" value = "path.to.your.main.class.hi">
<param name = "archive" value = "jar location">
<param name = "mayscript" value = "true">
<param name = "scriptable" value = "true">
...
<comment>
<embed
code = "path.to.your.main.class.hi"
archive = "your jar location"
scriptable = "true"
width = "100" height = "100"
name = "hi"
...
</embed>
</comment>
</object>
Then from the js you can access you object through the document using the id attribute in <object> or name in <embed> in the sample case document.hi. With the follow code you can invoke the HiThere(); method:
try{
// ie, ff
document.hi.HiThere();
}catch(Exception){
// chrome, safari, opera
document.hi[1].HiThere();
}
In order to execute with last java versions remember to meet the new java security requirements (manifest attributes http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html, jar signature... ).
You can call the applet methods in JavaScript:
To do this the applet should be launched from JavaScript, e.g.
<script src="https://www.java.com/js/deployJava.js"></script>
<script>
var attributes = { id: 'mainApplet', code:
'org.jazzteam.Example', archive: 'example.jar', width: 812, height:
635};
var parameters = {};
deployJava.runApplet(attributes, parameters, '1.7');
function actionInApplet(url) {
mainApplet.appletMethod(url);
}
</script>
In this case the applet is launched from JavaScript with id= 'mainApplet'. In the applet there is appletMethod() method, which we want to call. To do this you need to call the method related to JavaScript object with id name. You can also pass parameters to the called methods, as demonstrated in this example.
Also it is necessary to know that the applet method called from JavaScript should be privileged. To do this you need to wrap the method code in the following "wrapper":
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
//method code
return new Object();
}
});
This information is taken from the article:
Frequently Asked Questions during Java applet development

MEF Contrib Provider Model Not Importing Parts

I have been trying to use the configurable provider model for handling my MEF imports and exports from MEF Contrib (link). I've read the Codeplex documentation and Code Junkie's blog post (link); however, I can't seem to get the container to create the parts. Where am I going wrong?
Program.cs
namespace MEFTest
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
// [ImportMany("command", typeof(IHelp))]
public IEnumerable<IHelp> Commands { get; set; }
void Run()
{
Compose();
foreach(IHelp cmd in Commands)
{
Console.WriteLine(cmd.HelpText);
}
Console.ReadKey();
}
void Compose()
{
var provider = new ConfigurableDefinitionProvider("mef.configuration");
var catalog = new DefinitionProviderPartCatalog<ConfigurableDefinitionProvider>(provider);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
TestCommand.cs
namespace MEFTest
{
//[Export("command", typeof(IHelp))]
public class TestCommand : IHelp
{
private string _helpText = "This is a test.";
public string CommandName
{
get { return "Test"; }
}
public string HelpText
{
get { return _helpText; }
}
}
}
App.Config section:
<mef.configuration>
<parts>
<part type="MEFTest.TestCommand, MEFTest">
<exports>
<export contract="IHelp" />
</exports>
</part>
<part type="MEFTest.Program, MEFTest">
<imports>
<import member="Commands" contract="IHelp" />
</imports>
</part>
</parts>
</mef.configuration>
I don't get any build errors and it runs fine if I switch to the typical attribute-based system that is part of the MEF core (with the appropriate catalog too). Program.Commands is always NULL in the above example. I tried to just use a singular property instead of a collection and get the same results.
When I debug I can get the provider.Parts collection so I know it's accessing the configuration information correctly; however, I get an InvalidOperationException whenever I debug and try to drill into catalog.Parts.
Anyone have any experience as to where I'm going wrong here?
As documented here, you also need this in your config file:
<configSections>
<section
name="mef.configuration"
type="MefContrib.Models.Provider.Definitions.Configurable.PartCatalogConfigurationSection, MefContrib.Models.Provider" />
</configSections>
If you already have that, then it might be interesting to show us the stack trace of the InvalidOperationException that you get when accessing provider.Parts.
I had the same problems and could not get it to work, but here are some details:
It seems that ComposeParts() does not work as expected (at least in the version I used) because it uses static methods, based on Reflection to find all required Imports (so it seems that this part cannot be changed from outside of MEF). Unfortunately we want to use xml configuration and not the MEF attributes.
It works if you add [Import] attributes to the members of the class you you use with ComposeParts(). In your case this would be "Programm". In this case all exports defined in the configuration file will be found.
I could not find any documentation or examples on the MEF Contrib page relating to that problem. Also there is no unittest in the MEF contrib projekt that uses ComposeParts().
A workaround would be to use container.GetExportedValues() to retrieve the values, but in this case you have to set the classes members manually.
Hope that helps.