More on Umbraco, TinyMCE and Flash

by AaronPowell 3. February 2010 10:05

In a previous post Shannon explained how to customise TinyMCE for what HTML elements Flash actually supports, and he finished off the post with showing how to cleanup line breaks.

To do this he used an XSLT function called normalize-space, which is great if you’re using XSLT!

I was writing a service today which was using LINQ to XML to generate the XML for Flash, but that posed a problem, how do you deal with Flash wanting to do hard breaks on new line constants?

Easy, string.Replace to the rescue!

Here’s a handy little extension method you can drop into your code libraries:

public static string NormalizeSpace(this string s) {
	if(s == null) throw new ArgumentNullException("s");
	return s.Replace("\r\n", string.Empty)
		.Replace("\r", string.Empty)
		.Replace("\n", string.Empty);
}

Nice and easy (and unsurprisingly logical!).

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

.Net | Flash | Umbraco

Freeing up space on your server

by AnthonyDang 3. February 2010 06:24

Yesterday we went to install service pack 2 on a Windows  Server 2008 machine. It turns out you need at least 5GB free on C: which we didnt have. After deleting everything we possibly could, including running CCleaner and making the Page File non-existant we were still 400MB off the mark.

 

 Then I noticed a system file c:\hiberfil.sys which was 3GB.

 

Well it turns out that Windows Server 2008 still allocates space for a hibernate file. Who would want to hibernate their Live server?

 

Anyway, this is how to gain an exta 3GB...

 

C:\Users\Administrator>powercfg.exe /hibernate off

 

That's it!

 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Hosting

Problem: Inserting custom media types in the WYSIWYG of Umbraco 4.0.2.1 shows blank.gif instead of the correct Url

by AnthonyDang 25. January 2010 15:37
The Scenario
We had a custom media type called Image. We did this to store more information about each image that was uploaded.

The Problem
The CMS user wants to insert the image to the WYSIWYG of one of the content nodes but sees blank.gif inserted into the Url field when they click on the custom media type. This does not occur for standard Umbraco files.

Investigation
I used Charles to see what Umbraco was doing when a user clicks. Umbraco makes a call to ~/umbraco/dialogs/imageViewer.aspx to get the url. Let's take a look at the source code...


protected void Page_Load(object sender, System.EventArgs e) { //Response.Write(umbraco.helper.Request("id")); //Response.End(); // Put user code to initialize the page here if (Request.QueryString["id"] != null) { if (Request.QueryString["id"] != "") { //TODO: fix Nasty FAST'N'CANELINE HACK. .. int MediaId = int.Parse(Request.QueryString["id"]); image.Controls.Clear(); int fileWidth = 0; int fileHeight = 0; string fileName = "/blank.gif"; string altText = ""; try { cms.businesslogic.media.Media m = new cms.businesslogic.media.Media(MediaId); // TODO: Remove "Magic strings" from code. try { fileName = m.getProperty("fileName").Value.ToString(); } catch { try { fileName = m.getProperty("umbracoFile").Value.ToString(); } catch { fileName = m.getProperty("file").Value.ToString(); } } altText = m.Text; try { fileWidth = int.Parse(m.getProperty("umbracoWidth").Value.ToString()); fileHeight = int.Parse(m.getProperty("umbracoHeight").Value.ToString()); } catch { } string fileNameOrg = fileName; string ext = fileNameOrg.Substring(fileNameOrg.LastIndexOf(".")+1, fileNameOrg.Length-fileNameOrg.LastIndexOf(".")-1); string fileNameThumb = GlobalSettings.Path + "/.." + fileNameOrg.Replace("."+ext, "_thumb.jpg"); image.Controls.Add(new LiteralControl("<a href=\"" + GlobalSettings.Path + "/.." + fileNameOrg + "\" title=\"Zoom\"><img src=\"" + fileNameThumb + "\" border=\"0\"/></a>")); } catch { } image.Controls.Add(new LiteralControl("<script>\nparent.updateImageSource('" + GlobalSettings.Path + "/.." + fileName.Replace("'", "\\'") + "','"+altText+"','" + fileWidth.ToString() + "','" + fileHeight.ToString() + "')\n</script>")); } } }


Let's ignore the shamefullness of the code. We've all had our bad moments, and open source projects are bound to have some things like this. Lets comment on what the code does.

Notice this line:
string fileName = "/blank.gif";

Now notice that the bottom catch is empty. This catch is hit whenever a file does not have one of these attibutes:fileName, umbracoFile, file. So filename is never set to anything.

The solution
The last catch needs to get your custom media type. In our case:
Media m = new Media(MediaId);
fileName = m.getProperty("Image").Value.ToString();


That is the fix for Umbraco. So you have a couple options on how to implement it.

1. You can recompile Umbraco's source then redeploy.

2. If you don't want to recompile Umbraco you can can create a new file called ImageViewer.cs that inherits from umbraco.dialogs.imageViewer. Copy and paste the code, do your fix, then modify the ~/umbraco/dialogs/imageViewer.aspx file to inherit from your new file.

I.e. Change the header:
<%@ Page Language="c#" CodeBehind="imageViewer.aspx.cs" AutoEventWireup="True" 
Inherits="umbraco.dialogs.imageViewer" %>


To this:
<%@ Page Language="c#" CodeBehind="MyImageViewer.aspx.cs" AutoEventWireup="True" 
Inherits="My.Project.UmbracoExtensions.MyImageViewer" %>


The downside of both methods is that you will overwrite your changes if you upgrade Umbraco.


The awesome solution
Here is a solution that is awesomely hilarious. Using the already installed Urlrewriting.Net module that comes with Umbraco.

1. Create a new file called ImageViewer.aspx in your project somewhere. Mine was in ~/UmbracoExtensions/

Make the code behind inherit from umbraco.dialogs.imageViewer. Copy and paste the code, do your fix.

2. Open ~/config/UrlRewriting.config and add this entry:

<add name="ImageViewer"
          virtualUrl="~/umbraco/dialogs/imageViewer.aspx(.*)"
          rewriteUrlParameter="IncludeQueryStringForRewrite"
          redirectMode="Permanent"
          destinationUrl="~/UmbracoExtensions/ImageViewer.aspx$1"
          redirect="Application"
          ignoreCase="true" />


This redirects ~/umbraco/dialogs/imageViewer.aspx to your new ~/UmbracoExtensions/ImageViewer.aspx and passes the query string which allows the lookup of the file.

3. Open your ~/web.config and add /UmbracoExtensions/ to your umbracoReservedPaths under appSettings. This allows your newly created file to be redirected to.

That's it!

I find this solution absolutely hilarious! But it means I will not get undone by an upgrade. Hopefully they will eventually fix the imageViewer class to look for other files.

UPDATE
Ok after all that, I found out that you just need to change the alias name in the cmsPropertyType in the database.

First check if your file alias is being used more than once. In our case we had an Image file type, and a field in a document type called Image. So we have to modify the correct one.

Here is how to check your table:
SELECT * FROM [YOUR_DATABASE].[dbo].[cmsPropertyType]
  WHERE Alias LIKE 'Image'


To figure out which was which I did this really lazily. I had a synced db already on dev, so I just changed the alias of one to see if it would change in Umbraco. Note that you must bump the config for the alias to change in Umbraco.

Here is the sql to update your file type alias:
UPDATE [YOUR_DATABASE].[dbo].[cmsPropertyType]
  SET Alias = 'umbracoFile'
  WHERE Alias in ('YOUR_FILE_TYLE_ALIAS') // for multiple file types
  AND id !=  // line is optional



So it turns out there was no coding involved after all. Well at least I learned heaps about how Umbraco was structured :)


Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Comments Fail - They are back!

by Shannon Deminick 20. January 2010 12:39
We unfortunately didn't realize that comments on our site weren't working for a while... DOH!!!! It was due to us implementing some spam protection as we were getting hammered with it. So out with the old captcha, in with the new. Comments are all fixed now :)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Fail

A Few New Controls in Umbraco 4.1

by Shannon Deminick 19. January 2010 17:07

Currently the codebase in Umbraco 4.0.x uses quite a few iframes to render ‘controls’ as this functionality has existed this way from way back in the day and had never been upgraded… until now!

IFrames should be used sparingly, they have their uses but to render an iframe instead of a User Control is just adding overhead to the page, the client and server cpu/memory consumption and is not so cool. Here’s a nice benchmark on iframe performance: http://www.stevesouders.com/blog/2009/06/03/using-iframes-sparingly/ . As you can see, you should use iframes ONLY when completely necessary.

So on to the good news… Here’s some new controls that have been created in 4.1 (which will remove many of these iframes and make things a whole lot nicer to use)

  • /umbraco/controls/Tree/TreeControl.ascx
    • Will render a new tree based on the properties set
    • This makes the following Obsolete: treeInit.aspx, treePicker.aspx  (though, these pages are still used to load trees in modal windows for pickers but shouldn’t be used directly in your code)
      • Both of these pages now simply wrap the TreeControl
    • Example usage:
      <umb2:Tree runat="server" ID="DialogTree" 
          App="media" TreeType="media" IsDialog="true" 
          CustomContainerId="TinyMCEInsertImageTree" ShowContextMenu="false" 
          DialogMode="id" FunctionToCall="dialogHandler" />

    • There’s quite a few other properties that allow you to customize the tree to your needs
    • There’s also a very in-depth JavaScript API
  • /umbraco/controls/Images/ImageViewer.ascx
    • This is a nifty ajax control that will take a media item id and display the image
    • There’s a simple JavaScript library attached to it that allows you to dynamically update the media id to force an ajax request to refresh the image (amongst other methods)
    • This makes the following Obsolete: /umbraco/dialogs/imageViewer.aspx
      • The old codebase for imageViewer has been retained (though it should probably just wrap this control :)
    • Example usage:
      <umb3:Image runat="server" ID="ImageViewer" 
          ViewerStyle="ThumbnailPreview" LinkTarget="_blank" 
          ClientCallbackMethod="onImageLoaded" />

  • /umbraco/controls/UploadMediaImage.ascx
    • This control is essentially what you see when you load up TinyMCE, select the insert image button, then click on the ‘Create New’ tab. It contains the logic to enter a name, select a file to upload and select the media tree node to upload it to.
    • There’s a handy JavaScript callback method you can define so that it’s executed once the upload is complete. Tons of parameters are passed to the callback containing all of the information about the file/image.
    • This makes the following Obsolete: /umbraco/dialog/uploadImage.aspx
    • Example usage:
      <umb4:MediaUpload runat="server" ID="MediaUploader" 
          OnClientUpload="onFileUploaded" />

Now, on to the ‘pickers’! There’s quite a few picker controls in the codebase that all essentially do the same thing but the code for them was pretty much replicated everywhere, so i decided to streamline the whole thing which should make it quite easy for anyone to make their own pickers!

  • umbraco.controls.BaseTreePicker.BaseTreePicker (in the umbraco.controls assembly)
    • (yes i know the namespace and control are the same name, but that’s the way it is currently! :)
    • From the name, you would probably determine that this control is an abstract control… and you’d be correct.
    • This control implements: IDataEditor (so that it can be used as the data editor for Umbraco data type controls), and INamingContainer for obvious reasons.
    • This control exposes many properties and methods for you to modify and override to customize the picker.
    • The abstract properties are ModalWindowTitle (the title of the window that gets displayed) and TreePickerUrl (the URL to load in the modal window that is displayed)
    • This pretty much handles everything for a basic tree picker and the JavaScript has been refined to use real classes! Wow! ;)
  • umbraco.editorControls.mediaChooser (in the umbraco.editorControls assembly)
    • This is the umbraco data type to select a media item from the media tree
    • It’s been upgraded to inherit from BaseTreePicker and overrides the JavaScript rendered to support Tim’s new fandangled media picker (similar to the TinyMCE media picker)
  • umbraco.editorControls.pagePicker (in the umbraco.editorControls assembly)
    • This is the umbraco data type to select a content node from the content tree
    • It’s been upgraded to inherit from BaseTreePicker … it really doesn’t have any special functionality apart from setting the title and the tree picker url since all of the required functionality is in the BaseTreePicker
  • umbraco.controls.ContentPicker (in the umbraco assembly)
    • This pretty much does the same thing as all of the above controls, actually it’s nearly identical to the pagePicker only you have to specify the AppAlias and TreeAlias to load for the picker.
    • It’s been upgraded to inherit from BaseTreePicker also

So basically, everything will look pretty much the same, but will be a lot faster and MUCH easier to develop with if you’re creating custom packages or whatever. It’s all backwards compatible (apart from the JavaScripting) but under the hood is much different.

So now at least when you load up the TinyMCE insert image dialog, you end up with 1 frame (the modal dialog) instead of 4!

Oh yeah, and this hasn’t been checked in to the 4.1 branch as of today… perhaps next week!

Currently rated 5.0 by 6 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | Umbraco

Don’t deploy your .svn folders!

by aaronpowell 18. January 2010 04:37

Last year there was an article posted on TechChrunch about the problem of deploying your .snv folder live, it’s a really great way to give everyone your websites source code!

Recently though while tweaking our 2 Click ASP.NET Web Application Deployment with MSBuild to include a static folder consisting of the umbraco/ umbraco_client folders (which we leave excluded from the project to ensure performance of Visual Studio) I noticed that we were including the .svn folders!

We’re generating an ItemGroup like this:

<ItemGroup>
  <Umbraco Include="$(LocationWorkingWeb)\umbraco\**\*.*"/>
  <UmbracoClient Include="$(LocationWorkingWeb)\umbraco_client\**\*.*"/>
</ItemGroup>

Which recursively adds the files from those folder, including .svn.

Balls!

Sure it’s not really a problem, we’ve got no source code stored in those folders (and anyone who is putting their own source in umbraco or umbraco_client is asking for trouble), but by including them you’re pretty much doubling the size of the folder structure too!

Luckily it’s quite easy to solve. MSBuild has a build-in Exclude attribute, so you just need to change it to look like this:

<ItemGroup>
  <Umbraco Include="$(LocationWorkingWeb)\umbraco\**\*.*" Exclude="$(LocationWorkingWeb)\umbraco\**\.svn\**\*" />
  <UmbracoClient Include="$(LocationWorkingWeb)\umbraco_client\**\*.*" Exclude="$(LocationWorkingWeb)\umbraco_client\**\.svn\**\*" />
</ItemGroup>

It looks a bit weird, you’ve got to recursively exclude the recursive contents of the .svn folder :P

It’s all about making sure you only deploy what you should have on a production server, and it goes in hand with remembering that PDB != Product Deployable Bits.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | Umbraco

Changing the hostname of a SharePoint site

by aaronpowell 8. January 2010 10:44

We’ve recently set up a SharePoint server here at TheFARM which will run parts of our intranet and be our document management system.

So it got installed, but the problem was that it was installed onto a machine called mars. I made the obligatory jokes about ‘life on mars’ (admittedly I may have made the joke a few to many times :P) but at the end of last year we ran a competition to name the new intranet.

There were some fun names like SkyNet, and Randall, but ultimately the winning entry was TheBarn, which is very aptly farm-based.
But we had a problem, we don’t want to rename the server from mars (plus I’ve done that on SharePoint before, baaaaaaaaaaaaaaaaaaaaaaaaaaaaad idea), so how do you get SharePoint to accept http://thebarn when that’s not the machine name?

Unlike standard standard sites in IIS just adding a host header isn’t going to work, SharePoint will redirect you to the one it knows about, so although we were coming in via http://thebarn we’d end up at http://mars.

Hmmm…

Luckily it is actually very easy to do with SharePoint. SharePoint has the ability to Extend a web application:

image

So you navigate here, choose the Extend an existing Web application, select your site and enter the hostname (and set the port back to 80):

image

Now you’ll have a SharePoint site which listens on your new host header. You can go and delete the old one if you want (Remove SharePoint from IIS Web site) and then you’re done.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

Umbraco TinyMCE Customization for Flash Rich Text

by Shannon Deminick 7. January 2010 08:15

Flash doesn’t support most of the html elements of a standard web page. TinyMCE’s creators Moxiecode have thankfully given us the TinyMCE rules for flash here:

http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/valid_elements#Full_FlashMX_2004_rule_set:

So to get Umbraco & TinyMCE working to give your flash application the markup that it needs you need to modify your \config\tinyMceConfig.config file:

<validElements>
    <![CDATA[+a[href|target],
+b,
+br,
+font[color|face|size],
+img[src|id|width|height|align|hspace|vspace],
+i,
+li,
+p[align|class],
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+span[class],
+textformat[blockindent|indent|leading|leftmargin|rightmargin|tabstops],
+u
]]>
</validElements>

Then there’s the issue that flash treats real line breaks and <br/> tags exactly the same! This will probably cause you a few headaches trying to work that out. So to save you that headache, you need to output the rich text markup via XSLT to flash using the XSLT function: normalize-space

Something like:

<xsl:value-of select="normalize-space($myRichTextValue)" />

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

.Net | Umbraco | Flash

Excluding pages with URL Rewriting

by aaronpowell 23. December 2009 10:17

Today we had a mini site which the promotion had completed, but the site was to stay live with a few of the content pages staying live for people who come to view it.

Because the site was only a few pages there isn’t a CMS back-end, it’s just flat ASPX pages are stored in a single folder.
The problem is, that the pages which need to be available are also in the folder which the pages which are not longer accessible are.

There is a few ways in which I can take down the pages which people aren’t meant to access, firstly I could just delete them. That’d work, but that’d be a 404 error which isn’t really a good user experience (I could set the 404 redirect to be the home page, but the browser would still receive a 404 HTTP status).

So the next option is URL Redirection, lets crack out our UrlRewriting.config file and set up a rule. We’ll start with a rule like this:

<add name="RedirAllIndexedPagesToDefault" virtualURL="^(.*)/pages/(.*)" destinationUrl="$1/default.aspx" redirectMode="Permanent" redirect="Domain" ignoreCase="true" />

There, that’ll handle everything in our pages folder, but it doesn’t help with the pages which I want accessible. Say the pages I want accessible are TermsAndConditions.aspx and PrivacyPolicy.aspx, but I don’t want Entry.aspx accessible.
It’s just a matter of modifying my virtualURL to be a bit stricter, so now it looks like this:

<add name="RedirAllIndexedPagesToDefault" virtualURL="^(.*)/pages/(?![TP.*])(.*)" destinationUrl="$1/default.aspx" redirectMode="Permanent" redirect="Domain" ignoreCase="true" />

Now you’ll not be able to get to Entry.aspx, but the other two pages will still work just fine.

Sure it’s not great if you’ve got lots of pages (and if you did have lots of pages I’d hope there was a CMS to deal with it), but it’s good for mini sites which you want some pages but not others in a folder accessible.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

.Net

Easy way to check if object implements a specific interface

by Shannon Deminick 21. December 2009 04:56

Here’s a quick little snippet of how to check if one of your objects implements a specific interface. I’m not sure if there’s a ‘better’, or more efficient way to do this but I’ve been using this method to do this check for quite some time:

if (typeof(IMyInterface).IsAssignableFrom(myObject.GetType()))
{
	//Do stuff...
}

UPDATE:

Turns out there is a way easier and probably much more efficient way of doing this! I just didn't know it worked with interfaces too

if (myObject is IMyInterface) { //Do Stuff.. }

Much nicer!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.Net

// Website built by The FARM