Request a topic or
contact an Arke consultant
404-812-3123
Arke Systems Blog | Useful technical and business information straight from Arke.

Arke Systems Blog

Useful technical and business information straight from Arke.

About the author

Author Name is someone.
E-mail me Send mail

Recent comments

Archive

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2024

Custom Email Fields for WFFM

Have you ever needed to create a custom field type for Sitecore Web Forms for Marketers (WFFM)? Have you ever then needed to use that field type in the Send Email Message action in the To/From/CC field? By default, that editor only lets you select field of type Email. Here’s how you extend it to allow additional field types.

  1. Find the /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions/Send Email Message item.
  2. Add this to the QueryString field:

AllowedToTypes={84ABDA34-F9B1-4D3A-A69B-E28F39697069}|{1D2C0726-D622-4989-B545-4C37A63B97BB}

NOTE: {84ABDA34-F9B1-4D3A-A69B-E28F39697069} is the out of the box Email type, then add your custom types after that separated by a pipe.

AllowedTypes

Now when you use the Send Email Message save action, your custom type will appear in the To field. To control the other email fields on that dialog, use the following querystring parameters.

  • AllowedToTypes
  • AllowedFromTypes
  • AllowedCCTypes
  • AllowedSubjectTypes

For more specific information, reference “Sitecore.Forms.Shell.UI.Dialogs.SendMailEditor, Sitecore.Forms.Core” with Reflector.


Posted by Eric Stoll on Saturday, August 2, 2014 2:05 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Missing Disk Cleanup on Windows Server 2008 R2

Recently ran into a fun puzzler where my Windows Server 2008 R2 Machine had Disk Defragmenter available, but not Disk Cleanup.  After a few googles, I found this little fun gem.  In short, Disk Cleanup is part of what Windows calls 'Desktop Experience' which installs a lot of other items like Desktop Themes and the like.  Since most servers are meant for a specific function, Windows by default disables this.  This blog post article tells you how to either:

  • Turn Desktop Experience on
  • Copy over the two executables needed get back your Disk Cleanup

Kudos to Nathalie Vaiser.

https://support.appliedi.net/index.php?/Knowledgebase/Article/View/992/0/how-to-enable-the-disk-cleanup-tool-on-windows-server-2008-r2


Posted by Nicole Rodriguez on Wednesday, September 4, 2013 3:49 PM
Permalink | Comments (0) | Post RSSRSS comment feed

The 5 minute MVC CMS

[Code at the bottom]

 

I had a client that needed a solution that could meet the following requirements:

  • Must be able to add and remove page from their website
  • Must be able to change the content of each of the pages
  • Users of the website would need to be able to have a logon state
  • The pages would need to show up in the navigation menu
  • Must be able to do all of this without using a developer, re-engineering their site, installing a CMS system, or taking more than 4 hours of custom development time. 

 

They also had the following merits:

  • Those who would change the content were proficient in Html, CSS, and basic web technology
  • All pages would have the same layout
  • Existing website written in ASP.NET MVC

 

In the end, the content managers had access to a "PartialPages" folder that set under the main site on the webserver.  The managers could add, remove, and edit these files.  They could also update the SiteMap.xml file for these pages, allowing for the navigation menu to update based on their changes. 

 

CODE:

 

 AreaRegistration - Routing:

 

context.MapRoute(
    "FiveMinuteCMS_Default",  // Route name
    "FiveMinuteCMS/{id}",      // URL with parameters
    new { controller = "FiveMinuteCMS", action = "Pages", id = UrlParameter.Optional }
);

 

 Controller:

 

public ActionResult Pages(string id)
{
    PagesModel model = new PagesModel();
    model.Page = System.IO.File.ReadAllText(HttpContext.Server.MapPath
        ("~/PartialPages/" + id + ".html"));       
    return View(model);
}

 

Model:

 

public class PagesModel
{
    public string Page { get; set; }
}

 

Pages View:

 

@model MySampleProject.Areas.FiveMinuteCMS.Models.PagesModel
@{
    // Any layout will do
    Layout = "~/Areas/FiveMinuteCMS/Views/Shared/_Content.cshtml";
}

@Html.Raw(Model.Page)

 

 

Sample Partial Page file:

 

<div id=”PartialContentBody”>               
    <span>Hello World</span>
</div>

 

For the site map and navigation, I used Maarten Balliauw's MvcSiteMapProvider


Tags: , ,
Categories: ASP.NET | MVC | CMS
Posted by Trenton Adams on Tuesday, August 20, 2013 4:46 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Sitecore Workbox: No changes have been made

I had inherited a Sitecore instance from a previous vendor and one of the main questions the client had for me was about items in their workbox.  This specific Sitecore instance had over 29 different languages, over 35 different microsites and content editors from around the world.  When I opened the workbox, I found a whole list of items, all of them claiming 'No Changes have been made'.  When I tried to submit any of them, I would get a generic Sitecore error and the log files weren't helping me narrow it down.  I had assumed with all the moving parts, something catastrophic had happened.  Turns out the issue was rather simple.

[Sreenshot of over 200 items in this limbo state]

 

I opened the item and viewed the Standard fields.  Turns out the state was filled but not the workflow to which it belonged.

 

 

Once I had correctly assigned the items, the workflow worked as intended and I could clear the items for the client.  Be sure to check your workflows.  


Posted by Nicole Rodriguez on Wednesday, March 6, 2013 6:47 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Render unto c#

When it comes to CMS development (among other things in life) I’m a big fan of granularity and reusability. I believe that in a good solution architecture, both content and code are managed in discreet, granular pieces, which promotes both consistency and reusability.

That’s why it bothers me that so many Sitecore professionals react to the word “rendering” the same way a horse would. To my mind, a good solution has a geometric ratio of layouts to sublayouts, and sublayouts to renderings. Yet I see projects that are extremely sublayout-centric, with content IA and logic governing page layout.

Sitecore’s arsenal of presentation management tools, such as layout details, placeholder settings and rendering parameters, allows us as developers to truly empower our content owners. When implemented well, these features give the content authors what I like to call “controlled control” over their pages.

Unfortunately, we often see solutions where sublayouts are the dominant presentation component. Sublayouts are far less efficient than renderings, both in terms of performance and management. With sublayouts, there are all the ascx files to manage and deploy. And using sublayouts to present content seems to promote having a single component (sublayout) present multiple fields. This can dramatically reduce the solution’s flexibility – or worse, lead to having multiple components that are slight variations on each other, or have cumbersome logic (often wired to “control” fields in the content) to suppress content or change the presentation behavior.

Worse, some solutions rely almost entirely on the content tree to govern layout, such as by having fields in page templates that change the behavior of the layout, and/or by having sets of child items that code “bubbles up” into the page when they are present.

So why are renderings so often left out of solution architecture? I suspect that the problem lies in Sitecore training. Although Sitecore trainers do point out the different ways that renderings can be created, they tend to use XSL as the example technology in class (probably because it’s quicker to demonstrate --the trainer can show changes to an XSL rendering immediately, without compiling). Regrettably, this leaves many with a linkage in their minds between renderings as a Sitecore artifact and XSL as a technology. The oft-maligned rendering can be implemented using multiple technologies, yet many, many developers believe that renderings can only be developed using XSL.

I’m not going to wade into the great XSL debate here. I personally like XSL, but I rarely use it in Sitecore projects, for a number of reasons that I’ll get into that in a separate post. Suffice it to say that many developers, even if they know XSL, want to avoid it if for no other reason than to make their projects sustainable. XSL is a far more rare skill than c#, so it makes sense to ensure that future developers will be able to extend and maintain the project. And since there’s this misconception that “renderings = XSL”, the “baby” of a rendering-based architecture gets thrown out with the “bathwater” of XSL. And that’s a shame.

So let’s set the record straight. Renderings can and should be developed in c#. Actually, John West points out in his book “Professional Sitecore Development,” there are four types of renderings:

  1. XSL renderings
  2. Method renderings
  3. URL renderings
  4. Web Controls

Of these, Web Control renderings – controls that are implemented entirely in code and deployed in assemblies – are the least used yet most useful presentation component available. (In my next post, I’ll delve into the anatomy of a web control rendering.)

As a simple example, consider a page with a “core content” (“body”) area consisting of a title, a main image, and some body text. These three fields are defined in the page’s template. One way of handling this is to create a sublayout that renders these fields to the output (hopefully, at least, using field renderers). But what happens when the author does not want a title on a particular page (this is a simple example, so let’s not quibble over usability or SEO). Sure, the sublayout’s code-behind could suppress the <h1> when the field is empty or null. Or we could have a checkbox in the template to suppress the title.

What if the content author wants something other than a main image, like a flash or a video? What if they need to insert something between the image and the body? And after the body, they might need set of “spots” to point to other content?

So we might resort to having different sublayouts with variations on the content. This can lead to an unmanageable mess, creating confusion as to which sublayout does what. It also leads to redundant code, which makes ongoing maintenance and modification to the site much more challenging.

Another solution would be to put fields in the template to suppress content, or add content, or modify the presentation of content. Or we might create templates for child items that, when present, are bubbled up into the page. This puts management of presentation into the data. Sitecore is so well architected to give us excellent separation of content and presentation, so why fight that and force content to manage presentation?

I much prefer solutions that have very “light” layouts and sublayouts, with lots of renderings bound to placeholders. For the simple example, I would have a separate rendering each for title, main image, and body text, which I would bind to a placeholder in the sublayout for the core content area. Standard values in the item’s template would bind them by default, but the content owner would have the freedom to change the presentation as required. We can use features like thumbnails, rendering parameters, placeholder settings and compatible renderings both to assist them in the layout process, and to enforce brand or visual design requirements.

Most of my layouts and sublayouts are little more than div’s and placeholders. They exist to manage the geometry of the page or of regions of the page, not to present the actual content. Renderings bound to placeholders actually emit the content. Rendering parameter templates allow the editor to influence the source and behavior of the content in the page. Now, control over presentation and layout are managed in the presentation layer, and content is managed in the content layer. The design of the IA can break the content down into more manageable chunks, promoting reusability and avoiding redundancy.

To be fair, there are times when sublayouts are a better choice than renderings. For example, for forms or other situations where postback is required, I refer to use sublayouts (ascx) controls.. Also, in cases where the parts of the page structure are immutable, it is more efficient to statically bind renderings into sublayouts (by including them in the sublayout markup). This is fine for cases like fixed headers and footers, or when the site design requires an element (like a title) to always be present. There are also rare occasions when I allow a folder of child items to bubble up into a page, but even then, I usually use a placeholder-bound rendering to do the bubbling.

A highly granular architecture, which maintains separation of content from presentation, is hugely empowering to both developers and content editors. It promotes reusability of both code and content, shifts much of the responsibility for page assembly from code to configuration, and empowers editors with more control over the layout of their pages.


Posted by Andy Uzick on Thursday, January 24, 2013 6:52 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Sitecore Solution Custom Configuration

No matter how many times I look at a Sitecore web.config  I inevitably find something I’ve never seen before, or had forgotten about, or never really understood. There’s such an abundance of settings, pipelines, hooks, events --- all kinds of ways to modify and extend the application.

Good solution architecture should follow that same approach. As much as is practical, functional components should expose custom configuration settings, which allow the solution to be tweaked and extended without the need to deploy code. This includes such thing as connection strings, service URLs and communication parameters, pick list options, content locations, task behaviors, UI factors … anything that code or users need to make decisions about how the application should work.
There are four key places where configuration options can be created and managed:
  1. Web.config
  2. Config files in the /App_Config/Include folder
  3. Sitecore content items (typically in a global “MetaData” or “Settings” node)
  4. Static code classes, exposed as enums, constants, properties or methods
There are other, more obscure methods as well. For example, an application initialization event could create application-scoped objects, or even modify the running config. Cool as all that may be, these techniques are only useful in unusual circumstances, and can complicate analysis and troubleshooting.

There is no single right way for configuration management in a solution; rather, any given configuration setting should be managed in the location that makes the most sense for that function.

Using web.config


It is best to avoid using web.config to store custom application settings. Generally speaking, only Sitecore platform specific configuration should be handled here. Settings embedded within web.config can be a nightmare when deploying and reconciling across environments.
All configuration within the Sitecore section of the web config can be extended and modified within .config files (below). Rather than placing settings in web.config, it is better to group related configuration items within .config files, making management, deployment and troubleshooting much easier.

Content owners cannot make changes to web.congig, and developers might not be able to easily make changes here is some landscapes.

Web.config should be used only for very stable, solution-wide settings, and that, rarely (.config files can accomplish the same thing and are more manageable). Ideally, only Sitecore platform specific configuration – things that are part of the Sitecore release --- should be managed in web.config.

Using .config files


Sitecore allows any number of .config files to be created in the  /App_Config/Include folder. These config files require a specific XML structure, and are reconciled with web.config when Sitecore initializes, to create a “running config”. This running config represents what the web.config file would look like if all configuration were managed in one file.

Remember that Sitecore reconciles all of the .config files against web.config at application initialization. It is possible for two config files to modify the same configuration item, and it is difficult to predict what order the .config files will be applied.  Sitecore provides a utility at /sitecore/admin/showconfig.aspx to view the running config, which can be very helpful when troubleshooting.

Well organized .config fles are a very powerful way to handle configuration, as related configuration item can be aggregated into a single file. Configuration for settings, pipeline processors, events, etc  can be added to the “running config” here, which has the same effect as modifying web.config, but in a more manageable way. Modifying existing web config entries in external .config files allows the solution to have ‘default” behavior defined in web.config while making server, landscape or application specific changes to be made in separate file in separate environments.

This is the ideal place to manage config in the following circumstances:
  1. The configuration modifies or extends an existing setting, event or pipeline in web.config.
  2. This configuration might need to have different values in different environments.
  3. The configuration related to a module or package that needs to be distributable.
  4. Only developers or administrators should be allowed to change the configuration.

Settings in these files should follow the Sitecore setting syntax.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <settings>
            <!—Items to fetch per connection -->
            <setting name="MyDataConsumer.ItemsToFetchPerConnection" value="10" />

 

Note the naming convention for the name of the setting node. Using the dotted notation (MySettingGroup.MySettingItem) creates a pseudo-namespace that prevents name collisions. Remember that all settings in config files are merged together into a single running config when Sitecore initializes. Every setting needs to have a unique name when the configs are merged.

 It is a good practice to create an associated class that exposes these settings through properties or static methods.

public static int ItemsToFetchPerConnection
{
       get
       {
              return Sitecore.Configuration.Settings.GetIntSetting(
                     MyDataConsumer.ItemsToFetchPerConnection", 0);
       }
}

 

Not only can .config files extend Sitecore configuration, but they can even change Sitecore configuration by using a patch attribute.  John West’s blog post, “All About web.config Include Files with the Sitecore ASP.NET CMS” discusses config patching, and includes links to more in-depth reading.

In most cases, developers can create and deploy config files, at least within the developer and QA environments. Of course, content authors generally can’t touch config files.

Using content items


It is common practice to have a global settings section of the content tree, usually (not below) the home node. This node is usually called something like “MetaData” or “Settings”.

This is a great place to manage configuration in these circumstances:
  1. The setting is always the same across all landscapes and environments.
  2. Content authors, editors or power users should be able to manage the setting.
  3. The setting relates to interface elements, like the items to be included in a pick list in a data template or rendering parameter template.

Settings stored here are very easy to manage, but there is also some risk. Whenever a setting can affect the stability of the application, there should be tighter control over who can change it. Using security can help protect these settings while allowing them to be managed in the Sitecore UI, but moving them to .config or static classes protects them from UI users altogether.

Rather than creating a template that contains all of the fields needed for a particular “set” of settings, I generally create a several generic “settings” templates, and use them to create items in grouped folders under a “settings” item at the root of the content tree. Some useful templates include: General (text), Link (for references to content items), WebService (with fields for the URL and credential info), and File (for media library file items).

Settings managed in content cannot have different values for CM and CD (unless you use two different items).

The nature of the setting also comes into play. When the setting represents a list of allowable values in a pick list in the content UI, this is really the only place to manage it (because the items in these lists are defined as data sources for the field). The danger is that these values often govern the behavior of code, and unexpected values can cause the code to throw errors. Again, security can help prevent unintended changes to these settings.

Using static classes


Settings in static classes (constants, properties or enums) is the best scenario from a performance perspective, but is also the least manageable method. Changes to these settings can only be accomplished with a code deployment.

This is a good approach for things that should only be changed when code is changing anyway, or only affect code. Static code configuration should also be considered when performance is a concern. For example, there are cases where a known predictable content item must be referenced frequently in code. Storing the GUID of this item in a static class makes the code much more efficient when accessing the item. If the GUID is unlikely to ever change, this is an excellent approach. Note that Sitecore exposes the Sitecore.FieldIDs and Sitecore.ItemIDs classes where the GUIDS of well-known items are stored.

In fact, this is a good way to “bootstrap” settings that are managed in the Sitecore content tree. Create a property in code with the GUID of the folder that contains the settings. This avoids hard-coding the location of the settings, and allows the settings to be accessed even if the location of the settings folder changes.

Settings location guidelines


 

 
web.config
Config file
Content item
Static class
Types (what does this setting affect?)
Part of the Sitecore platform
Related to code
 
Related to infrastructure
 
 
 
Related to content
 
 
 
Roles (who manages this setting?)
Developer
 
System administrator
 
 
Site architect
 
Business owner
 
 
 
Environments (CM vs CD)
Same on all environments
Different in each environment
 
 
 
Volatility (how often does it change?)
Frequently
 
 
 
Infrequently
 
Risk (impact of a mistake)
Changes affect entire application
 
Changes affect part of the application
 
 
Changes affect availability of data
 
 
Changes are cosmetic or content only
 
 
 


Posted by Andy Uzick on Wednesday, January 16, 2013 4:03 PM
Permalink | Comments (0) | Post RSSRSS comment feed

IE7 not displaying tr/td background color

This was a little fustrating to find, but for those of you who are applying a background-color attribute to your table tr's and td's and are not seeing the color appear in IE7 or lower, check your reset.css.  If you reset.css has 'tr:background:transparent' applied to it, your color will not show even with the '!important' tag.  Check the very top of your reset.css.  Usually the tr is lumped together with all default html tags so its easy to miss.


Categories: CSS
Posted by Nicole Rodriguez on Tuesday, September 18, 2012 9:22 PM
Permalink | Comments (0) | Post RSSRSS comment feed

I'm not buying that on my iPhone

The overwhelming evidence of consumers shifting to mobile is forcing brands to quickly evaluate how to incorporate tablets and smartphones into their digital strategy. Nielsen research showed that 46 percent of US mobile consumers had smartphones as of Q42011, and that figure has continued to quickly grow. In fact, a recent study by IDC revealed that more people in the United States will access the web via mobile devices than via wireline computers by 2015. The drive to mobile begs the question: what's the best path to monetize mobile?

According to research by Adobe, tablet users spend over 50% more on online purchases when compared with smartphone users. Adobe analyzed roughly 16.2 billion online transactions from 150 top U.S. retailers in 2011 for the study. Additionally, the report concluded that tablet users are three times more likely to make a purchase than smartphone users. The findings are not surprising when considering that the browser on a tablet is more similar to one a PC than on a smartphone. For example, in-line videos on an iPad do not play within a native player as they do on an iPhone. Essentially, the display size on the smartphone, which is typically 3.5" to 4.7" does not provides enough room for a user to view a website. Thus, the smartphone is relegated to in-aisle product comparisons experiences whereas the full-form tablets are used for in-home browsing and purchases.

The study demonstrates that brands need to look beyond a one-size-fits-all for mobile screens. Instead, brands need to consider how to shift visitors from one screen to the next. Beyond simply moving smartphone visitors that are browsing products on-the-go to a full website experience on a tablet or a desktop, brands can also take advantage of in-app purchases to convert visitors into customers. But in the next two years, brands should expect to adjust their mobile strategies again as the display size on smartphone devices expand. For example, Samsung is rolling out the Galaxy Note in Q1 2012 which will feature a whopping 5.3" display. As these devices become more commonplace, the line between smartphones and tablets will blur and consumer will become more accustomed to completing purchases via the mobile phone browser instead of defaulting to a mobile application or a tablet.


Categories: Mobile
Posted by Tomer Tishgarten on Sunday, February 5, 2012 4:39 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Passing query to Custom Google Search on your webpage

Stackoverflow got me the answer to this.

If you're using Custom Google Search on your website and you have a small textbox on each page that is supposed to 'pass' that query to your search page (ultimately passed into your Google search post action), you should do the following: 

Instead of the code Google provided you with to embed, take your unique key provided by Google and place it in the '***my key***') setting of the first code snippet below.  What this is doing is creating a new instance of your custom google search with your unique key and drawing out the results (*cse*) and forcing it to submit the action (execute) with your parameters ($q). 

 

    google.load('search', '1', { language: 'en' });

    function OnLoad() {
        var customSearchControl = new google.search.CustomSearchControl('009045124056933145342:5wmgo53sugc');
        customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
        customSearchControl.draw('cse');
        customSearchControl.execute(search_value);
    }
    google.setOnLoadCallback(OnLoad);

 

On my click event for my search text box on every page, I sanitized the query (this is a very basic sanitize, you should alter as necessary to protect your site!) and appended those parameters to the query string being sent to my search results page.

private String SanitizeUserInput(String text)
        {
            if (String.IsNullOrEmpty(text))
                return String.Empty;

            String rxPattern = "<(?>\"[^\"]*\"|'[^']*'|[^'\">])*>";
            Regex rx = new Regex(rxPattern);
            String output = rx.Replace(text, String.Empty);

            return output;
        }

        protected void Button1_Click(object sender, ClickEventArgs e)
        {

            Response.Redirect(
                String.Format(
                Page.ResolveUrl("~/{MySearchPage}.aspx?q={0}"),
                    HttpUtility.UrlEncode(SanitizeUserInput({mysearchtextbox}.Text.Trim()))
                    ),
                false
                );
        }



On my search results page, I remove those parameters with the below function and pass them into my $q variable.

function getQuerystring(key, default_) {
if (default_ == null) default_ = "";
key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
var qs = regex.exec(window.location.href);
if (qs == null)
return default_;
else
return qs[1];
}


Posted by Nicole Rodriguez on Wednesday, August 24, 2011 9:36 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Parsing and Validating Phone Numbers in CRM 2011

First off, I would like to thank Joe Gill for getting me started down the right path.  In fact, I'm going to suggest that everyone click that link so you can use his helpful screenshots to navigate where to put the JS I'm about to post. 

In any case, I had not seen a full example of parsing a phone number in CRM 2011 as I had with CRM 4.0.  Since it is such a common need, I decided to make my own.  The following code will strip out all special characters, check and make sure it's a valid set of numbers, and then push it back to the field, parsed properly.  This is limited to 10-digit phone numbers at the moment, but the core structure should be easily expanded if you need different types of validation.

The nice thing is, this can point at any entity, and any attribute that holds a phone number.  I strongly recommend adding this to your standard JS library for all CRM 2011 projects.

function validatePhone(context)
{

var phone =context.getEventSource().getValue();
var sTmp = phone.replace(/[^0-9]/g, "");
phoneRegex = /^\d{10}$/;

if( !sTmp.match( phoneRegex ) )
   {
   event.returnValue = false;
   alert("Phone must contain 10 numbers.") ;
   }
else
  {
   var sTmpClean =  "(" + sTmp.substr(0, 3) + ") " + sTmp.substr(3, 3) + "-" + sTmp.substr(6, 4);
   context.getEventSource().setValue(sTmpClean);
  }
}


Posted by Wayne Walton on Wednesday, June 22, 2011 4:34 PM
Permalink | Comments (0) | Post RSSRSS comment feed