<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rssdatehelper="urn:rssdatehelper"><channel><title>Blog</title><link>http://www.istern.dk</link><pubDate></pubDate><generator>umbraco</generator><description></description><language>en</language><item><title>Chiliplanter på chillicious.dk</title><link>http://www.istern.dk/blog/2010/8/18/chiliplanter-paa-chilliciousdk.aspx</link><pubDate>Wed, 18 Aug 2010 14:49:30 GMT</pubDate><guid>http://www.istern.dk/blog/2010/8/18/chiliplanter-paa-chilliciousdk.aspx</guid><content:encoded><![CDATA[ 
<p>Lidt reklame !!!!!</p>

<p>S&aring; har jeg endelig f&aring;et nogle fine chiliplanter som
s&aelig;lges p&aring; mit lille hobbyprojekt</p>

<p>chillicious.dk her er et l<a
href="http://chillicious.dk/chiliplanter.aspx"
title="chiliplanter">link hvo i kan se dem fine chiliplanter</a>
desv&aelig;rre er der kun ganske f&aring; tilbage s&aring; man skal
skynde sig lidt hvis man &oslash;nsker at f&aring; fat i en af de
fine sager.</p>

<p>Men tjek dem ud.</p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>Content editor And Core Editor open at the same time</title><link>http://www.istern.dk/blog/2010/7/6/content-editor-and-core-editor-open-at-the-same-time.aspx</link><pubDate>Tue, 06 Jul 2010 10:31:00 GMT</pubDate><guid>http://www.istern.dk/blog/2010/7/6/content-editor-and-core-editor-open-at-the-same-time.aspx</guid><content:encoded><![CDATA[ 
<p>For thoose of you that where attending the dreamcore in
Copenhagen, know about this nice little easy piece of code,
Actually it is One line of code that can help you a lot in sitecore
backend. I have for while been doing a lot of work in the core
content editor and offen had to switch back and forth between the
Core content editor and Master database content editor. So after
seen Raul Jimenz Presentation af Dreamcore aI thought wow cool I
what the same functionality just with a minor twist, I would like
my shortcut to be placed in Tray of the Desktop of the sitecore
backend. I know this is easy to do, but sometimes easy to do things
get overlooked I now I did for this. Okay here we go, lets start
with adding the an icon with an click action in the tray let's
start by going to the core editor go to:</p>

<p><br />
 /sitecore/content/Applications/Desktop/Tray/CoreContentEditor</p>

<p>and insert an item as shown</p>

<p><img src="/media/3688/coredb1_458x374.jpg"  width="458"  height="374" alt="coredb1"/></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><img src="/media/3701/tray.jpg" width="302" height="139" alt="tray3"/><br />
 Okay now open the command.config file for you sitecore solution
and add the with reference to to command you wrote in core editor
of sitecore. Remenber that syntax is FullClassName,NameSpace.</p>

<p>&lt;command name="Tray:CoreContentEditor"
type="CoreContentEditor.TrayCommandCoreContentEditor,CoreContentEditor"
/&gt;</p>

<p><br />
 Now tho the code it is simple one line of code.</p>

<pre class="brush:c#">
namespace PT.CoreContentEditor
{
  public class TrayCommandCoreContentEditor : Command
  {
  
    public override void Execute(CommandContext context)
    {
      Sitecore.Shell.Framework.Windows.RunApplication("Content Editor", "sc_content=core");
    }
  }
 
}
</pre>

<p><br />
 And now let's see it in action</p>

<p><br />
 <img src="/media/3693/openatthesametime_467x350.jpg"  width="467"  height="350" alt="openatthesametime"/></p>

<p><br />
 Again I know it is easy to do, but i think it is so nice to could
switch back and forth without having to open the content editor
everytime. Note you could also make a shortcut for the webdatabase.
Changing sc_content=core to sc_content=web.</p>
]]></content:encoded></item><item><title>What will make users comment blogposts ?</title><link>http://www.istern.dk/blog/2010/6/15/what-will-make-users-comment-blogposts-.aspx</link><pubDate>Tue, 15 Jun 2010 21:56:35 GMT</pubDate><guid>http://www.istern.dk/blog/2010/6/15/what-will-make-users-comment-blogposts-.aspx</guid><content:encoded><![CDATA[ 
<p style="margin-bottom: 0cm;">&nbsp;</p>

I have had this blog for sometime now, and i can see more and more
people have started read my posts, But not many or more correct not
any, are <span>writing</span> <span>comments</span> to my posts.
That made me think either I'm <span>writing</span> easy to read and
understand and self <span>explaining</span> <span>posts, but i
seriously doubt that, or the post are so bad and not worth
commenting, I hope this is not the case.</span> 

<p style="margin-bottom: 0cm;"><span>So what could I do to improve
my blog, and why don't my</span> <span>visitors</span>
<span>add</span> <span>comments</span><span>. So my question is
what will make you write comments for blogposts in the future
?</span></p>

<p style="margin-bottom: 0cm;"><span>With out any</span>
<span>comments</span> <span>or feedback it is hard to improve the
posts and this blog overall.</span></p>

<p style="margin-bottom: 0cm;"><span>With comments each post
becomes more interactive and hopefully can help even more
people.</span></p>

<p style="margin-bottom: 0cm;"><span>So let me know if you have any
specific themes or question you would like me to blog about, or how
to improve the posts so you will and commets.</span></p>

<br />
<br />
]]></content:encoded></item><item><title>Usersessions in sitecore (logout users from backend)</title><link>http://www.istern.dk/blog/2010/6/7/usersessions-in-sitecore-(logout-users-from-backend).aspx</link><pubDate>Mon, 07 Jun 2010 10:42:52 GMT</pubDate><guid>http://www.istern.dk/blog/2010/6/7/usersessions-in-sitecore-(logout-users-from-backend).aspx</guid><content:encoded><![CDATA[ 
<p>&nbsp;</p>

<p>The number of usersession that is possible to have open in
sitecore depend onj the licens, which is fair enough. But the task
for an administrator to end hanging usersession seems somewhat
headless. The administrator have to logout, to get a list of active
user sessions, and then choose to end hanging or not used sessions.
This might be fine in minor solutions but I think this might pose a
problem in solutions where a user with the "Is Adminstrator" flag
is set to true can be hard to find. He might be working in
different office or just generally be hard to get a hold of. It
doesn't require you have the "Is administrator" flag to end session
but it is required to get the list of active sessions. You don't
even have to be logged in to sitecore to end active session, if
presented with the option to end active session anonymous users
could do so. My idea is to help local administrators with
functionality to end session with out leaving the backend, or
having to log out or anything like that. Since sitecore is one big
tool box I will build it as shortcut in the tray of sitecore.<br />
 Okay so we start, all our work is done in the core database and it
only contains minimal coding. We start with making the tray icon.
In the core database we go to content/applications/Desktop/tray and
add a item I will call it UserSessions the Data section of the item
find the click attribute and add the command name, this will also
have to go in the command file we get back to that. I also and icon
for the tray I have choosen the standard user icon.</p>

<p><br />
 <img src="/media/3613/ss1_405x273.jpg"  width="405"  height="273" alt="userhelper1"/></p>

<p><br />
 Now with the tray icon shortcut in place you should be able to see
it in th start bar just save the item and hit F5</p>

<p>&nbsp;</p>

<p><img src="/media/3618/ss2.jpg" width="313" height="60" alt="userhelper2"/></p>

<p>Now we will add the command to the App_Config/Commands.config
add the following line</p>

<p>&lt;command name="Tray:UserSessionViewer"
type="UserHelper.UserhelperTrayCommand,UserHelper" /&gt;</p>

<p><br />
 I will add this little user feature helper as an application so we
need to add an application and layout for the application in the
core database. We start with adding the layout "core database" go
to sitecore/layout/applications and add a new layout in the data
section in path write the physical path to layout you will create
in the next step.</p>

<p>&nbsp;</p>

<p><img src="/media/3623/ss3_442x200.jpg"  width="442"  height="200" alt="suerhelper3"/></p>

<p><br />
 Next we will add the application again this is done in the core
database go to sitecore/content/Applications/ and add a new
application pull on the the layout we just created make sure you
can see it in the layout section for the item. Also note the Id for
your application, we will have to use it in the code part.</p>

<p><br />
 <img src="/media/3628/ss4_469x401.jpg"  width="469"  height="401" alt="userhelper4"/></p>

<p><br />
 Okay now we are done with the configuration in sitecore now to
code part.<br />
 First we will start we the Tray click command which is pretty
simple note that is hardcode the id for our application and the
database I getting the item from.</p>

<p>&nbsp;</p>

<p>Now we have something that handle the click on the Tray command
no we will code the popup or application window. First the frontend
code for the application. The frontend code shows when the user
session started and when the last request was made info need to
take into account which user sessions you should end</p>

<pre class="brush: xml">
&lt;div class="taskInfoWindow"&gt;
  &lt;div class="SystemTime&gt;
  &lt;span class="Literal"&gt;System Time&lt;/span&gt;
  &lt;span class="Time"&gt;&lt;%# SystemTime %&gt;&lt;/span&gt;
  &lt;/div&gt;
    &lt;div class="tasks"&gt;
      &lt;asp:Repeater ID="taskRepeater" runat="server" DataSource="&lt;%# ScheduleItems %&gt;"
        OnItemCommand="taskRepeater_ItemCommand"&gt;
        &lt;HeaderTemplate&gt;
          &lt;table&gt;
            &lt;thead&gt;
              &lt;tr class="informationHeader"&gt;
                &lt;td class="Icon"&gt;
                  *
                &lt;/td&gt;
                &lt;td class="Literal"&gt;
                  Task name
                &lt;/td&gt;
                &lt;td class="Literal"&gt;
                  Is Due
                &lt;/td&gt;
                &lt;td class="Time"&gt;
                  Last run
                &lt;/td&gt;
                &lt;td class="Time"&gt;
                  Next run
                &lt;/td&gt;
                &lt;td class="Button"&gt;
                  Execute Task
                &lt;/td&gt;
              &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
        &lt;/HeaderTemplate&gt;
        &lt;ItemTemplate&gt;
          &lt;tr class="scheduledItem &lt;%# Container.ItemIndex == 0 || Container.ItemIndex % 2 == 0 ? "even" : "odd"   %&gt;"&gt;
            &lt;td class="Icon"&gt;
              &lt;img src="/sitecore/shell/Themes/Standard/&lt;%#((ScheduleItem)Container.DataItem).Icon%&gt;"
                alt="&lt;%# ((ScheduleItem)Container.DataItem).DisplayName %&gt;" /&gt;
            &lt;/td&gt;
            &lt;td class="Literal"&gt;
              &lt;%# ((ScheduleItem)Container.DataItem).DisplayName%&gt;
            &lt;/td&gt;
            &lt;td class="Literal"&gt;
              &lt;%# ((ScheduleItem)Container.DataItem).IsDue%&gt;
            &lt;/td&gt;
            &lt;td class="Time"&gt;
              &lt;%# ((ScheduleItem)Container.DataItem).LastRun.ToString("HH:mm dd/MM-yyyy")%&gt;
            &lt;/td&gt;
            &lt;td class="Time"&gt;
              &lt;%# ((ScheduleItem)Container.DataItem).NextRun.ToString("HH:mm dd/MM-yyyy")%&gt;
            &lt;/td&gt;
            &lt;td class="Button"&gt;
              &lt;asp:LinkButton ID="LinkButton1" Text="Execute" CssClass="SortButton" runat="server"
                CommandName="Execute" CommandArgument="&lt;%# ((ScheduleItem)Container.DataItem).ID %&gt;" /&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;/tbody&gt;
        &lt;/ItemTemplate&gt;
        &lt;FooterTemplate&gt;
          &lt;/tbody&gt; &lt;/table&gt;
        &lt;/FooterTemplate&gt;
      &lt;/asp:Repeater&gt;
    &lt;/div&gt;
  &lt;/div&gt;
</pre>

<p>Now to the code behind, I am only using standard sitecore
functionality nothing fancy here other then the click event for the
repeater that end the selected user session.</p>

<pre class="brush: c#">
using Sitecore.Data;
using Sitecore.Security.Accounts;
using Sitecore.Web.Authentication;

namespace Userhelper.Presentation
{
  public partial class UserSessionsView : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      DataBind();
    }

    public IEnumerable UserSessions
    {
      get
      {
        return DomainAccessGuard.Sessions;
      }
    }


    protected void userRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
      string id = e.CommandArgument.ToString();
      switch (e.CommandName)
      {
        case "Execute":
          EndSession(id);
          break;
      }
    }

    private void EndSession(string sessionID)
    {
      DomainAccessGuard.Kick(sessionID);
    }

  }
}

</pre>

<p><br />
 This is how I looks when we done</p>

<p><img src="/media/3633/sslast_458x80.jpg"  width="458"  height="80" alt="userhelperlast"/></p>

<p>The styling part is left for you. With this little userhelper
you can set security on the tray icon so local administrator can
see the tray icon and all other users have denied read access so
only users with elevate security settings can end user
sessions.</p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>A personal project</title><link>http://www.istern.dk/blog/2010/6/4/a-personal-project.aspx</link><pubDate>Fri, 04 Jun 2010 20:54:38 GMT</pubDate><guid>http://www.istern.dk/blog/2010/6/4/a-personal-project.aspx</guid><content:encoded><![CDATA[ 
<p>I haven't been writting any post for a while, because i've
started a new minor business project.&nbsp; It is more a hobby
business project, selling chiliseed and everything related to
growing chilli's the shop is not open yet but you can check out
here is a link <a href="http://chillicious.dk"
title="Chillicious.dk">Chillicious.dk</a>. The project base is
stilling missing some items, but i'm currently building some
business relations with partnes abroad. So more items will come in
the near future. SO go have a look, and hopefully you will buy a
lot of stuff..</p>

<p>This new hobby project doesn't mean that I will stop writing
post. I've allready have some ideas in the pipeline with code
allready made just waiting for me to have the time to write a post
about it.</p>
]]></content:encoded></item><item><title>System Alert in sitecore</title><link>http://www.istern.dk/blog/2010/4/27/system-alert-in-sitecore.aspx</link><pubDate>Tue, 27 Apr 2010 08:48:54 GMT</pubDate><guid>http://www.istern.dk/blog/2010/4/27/system-alert-in-sitecore.aspx</guid><content:encoded><![CDATA[ 
<p>When working with large Sitecore implementation and customers
that have a lot of editors maintaining the content of their
website, often makes updating the system becomes a hurdle. Because
editors may or may not work in on the same floor or even the same
building, so even if you have an contact person who's
responsibility is to notify editor about the downtime, it is
possible that one or more editors haven't heart about the downtime
and haven't save the what they where doing the second the system is
taken offline, a valuable work may have been lost.<br />
 So I thought what would be more smart the implementing a System
alert/ notifier system that alert the users about the forthcoming
downtime. This Alert could as in this example be a simple
javascript alert.<br />
 My solution is build around simple Javascript calling a webservice
which looks for alert placed inside sitecore and display them as a
simple javascript alert. Yes some may argue that I have some
hardcoded path string and what have we not, but it is left to you
to move these to fx. The web.config. Even more this solution I
maybe a little over the edge when looking at the implementation,
but I se so many usages for this so I went ALL-IN as implemented
with interface and using a provider model. The solution is build
and tested against a Sitecore 6.2, but nothing wrong with using on
other Sitecore versions.<br />
 But here goes first the javascript since Sitecore editors have
three different editors Page Edit, Content Editor and the Desktop.
So we need to include the javascript in three different files, and
because of the we need to ensure that the file is only loaded once
so logged into the Desktop and opening the content editor doesn't
give two warnings, hence the cookie check. Now to javascript, it's
all simple stuff.<br />
 The javascript should be include in these three files<br />
 Webedit:<br />
 sitecore\shell\Applications\WebEdit\WebEditRibbon.aspx<br />
 Content Editor:<br />
 sitecore\shell\Applications\Content Manager\Default.aspx<br />
 Desktop:<br />
 sitecore\shell\Applications\Startbar\Startbar.xml</p>

<pre class="brush: javascript">
/* Function for calling the webservice                             */
function callWebservice() {
  var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  xmlhttp.open("GET", "/Components/SystemNotifier/AjaxWebservice/SystemNotifier.asmx/GetAlerts", false);
  xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xmlhttp.send();

  if (xmlhttp.status == 200) {
    var str = xmlhttp.responseXml.getElementsByTagName("string").item(0).text;
    return str;
  }
}

/* function that Get system alerts */
/* update timer by calling the webservice    */
function GetSystemAlerts() {
  var alertString = callWebservice();
  if (alertString != "") {
     alert(alertString);
     //increase time to next call so we dont get same alert twice
     setTimeout("GetSystemAlerts()", 125000);
  }
  else {
    setTimeout("GetSystemAlerts()", 60000);
  } 
}

var cookieName = "SitecoreSystemNotifier";

function writeCookie() {
 document.cookie = cookieName;
}

function cookieExists()
{

 if (document.cookie.length &gt;0 )
 {
   var offset = document.cookie.indexOf(cookieName);
   if (offset != -1)
     return true;
   return false;
 }
 return false;
}


function init(){
 if(!cookieExists()){
  writeCookie();
  //SetTimeout in ms
  setTimeout("GetSystemAlerts()", 60000);
 }
}

init();
</pre>

<p>&nbsp;</p>

<p>Okay now that we have the javascript we need the webservice to
be called. It's fairly simple when using the Provider.</p>

<p>&nbsp;</p>

<pre class="brush: c#">
namespace SystemNotifier.AjaxWebservice
{
  /// 
  /// Summary description for SystemNotifier
  /// 
  [WebService(Namespace = "http://pentia.dk/")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  [System.ComponentModel.ToolboxItem(false)]
  // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
  [System.Web.Script.Services.ScriptService]
  public class SystemNotifier : WebService
  {

    [WebMethod]
    public string GetAlerts()
    {
      ISystemAlert alert = AlertProvider.NextAlert;
      if (alert != null)
        return alert.Text;
      return "";
    }

    private SystemAlertProvider _provider;
    private SystemAlertProvider AlertProvider
    {
      get
      {
        if (_provider == null)
          _provider = new SystemAlertProvider();
        return _provider;
      }
    }
    
  }
}
</pre>

<p>And now to the provider implementation</p>

<pre class="brush: c#">
 public class SystemAlertProvider
  {
    private IEnumerable _alerts;
    public IEnumerable Alerts
    {
      get {
      if(_alerts == null)
       _alerts = GetAlertsFromSitecore();
       return _alerts;
      }
    }

    private TimeSpan timespan = new TimeSpan(0, 1, 0);
    private IEnumerable GetAlertsFromSitecore()
    {
      ChildList childList = AlertRootItem.Children;
      foreach(Item child in childList)
      {
        ISystemAlert alertItem = new SystemAlert(child);
        if(alertItem.AlertTime &gt; DateTime.Now.Subtract(timespan))
          yield return alertItem;
      }
    }

    private const string sitecoreRootPath = "/sitecore/system/SystemAlertNotifier";
    private Item _rootItem;
    private Item AlertRootItem
    {
      get
      {
        if(_rootItem == null)
         _rootItem = Database.GetItem(sitecoreRootPath);
        return _rootItem;
      }
    }

    private const string _databaseName = "master";
    private Database Database
    {
      get
      {
        return Database.GetDatabase(_databaseName);
      }
    }
    public ISystemAlert NextAlert
    {
      get
      {
        if(Alerts.Count() &gt; 0)
          return Alerts.OrderBy(w =&gt; w.AlertTime).First();
        return null;
      }
    }
  }
</pre>

<p>And finally the Alert interface and implementation of the
same.</p>

<p>Inteface</p>

<pre class="brush: c#">
public interface ISystemAlert
  {
    DateTime AlertTime { get; }
    String Text { get; }
  }
</pre>

<p>Implementaion</p>

<pre class="brush: c#">
public class SystemAlert : ISystemAlert
  {
    public SystemAlert(Item item)
    {
      Item = item;
    }

    private Item Item
    {
      get;
      set;
    }

    private const string _alertTimeField = "SystemAlert_AlertTime";
    public DateTime AlertTime
    {
      get
      {

        DateField dateField = Item.Fields[_alertTimeField];
        return dateField.DateTime;
      }
    }

    private const string _textField = "SystemAlert_Text";
    public string Text
    {
      get { return Item[_textField]; }
    }
  }
</pre>

<p>Now we got all the code working so now we need to have someway
to get the info, let's use a sitecore item. So here is a snapshot
of the how my sitecore item looks.</p>

<p><img src="/media/3579/sysemalert2_500x130.jpg"  width="500"  height="130" alt="sys2"/></p>

<p>So this is pretty much everything you need to have a system
alert system up and running inside sitecore. Remember to edit
hardcode root path to system alert root folder.<br />
 You can download the project in the download section <a
href="/media/3552/systemnotifier.rar">link here.</a></p>

<p>And hope you can see the posiblities in this solution or
implementaion, you could scheduled downtown and have email alert,
downtime calendar and much much more hope you enjoy,</p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>Seamless integration of external photo gallery</title><link>http://www.istern.dk/blog/2010/3/12/seamless-integration-of-external-photo-gallery.aspx</link><pubDate>Fri, 12 Mar 2010 21:45:09 GMT</pubDate><guid>http://www.istern.dk/blog/2010/3/12/seamless-integration-of-external-photo-gallery.aspx</guid><content:encoded><![CDATA[ 
<p>In this post I will give one way, or my take on how-to integrate
an external photo gallery seamless in to your website. Some of the
advantage in doing this is you save room/space on your local
webhost, and the load on the serve if you have large photo/images
since these are not load in another thread on an external server.
Off course there are disadvantage as well the gallery provide have
to be online for this to work, and you have to maintain gallery
content and web content on two different websites. On the other
hand you if you choose one of the large providers flickr or picasa,
you get some great photo gallery functionality tagging of images
and galleries and more.</p>

<p>So i don't what to build the new Picasa or a like, so i will
only provide functionality for showing frontend relevant images and
associated information. In near future there will be a post on
how-to use this post to integrate into Umbraco.</p>

<p>For this post i have chosen to integrate up against Google's
Picasa so to start with you can go and download the google-gdata
API you can get it here</p>

<p>The documentation i used to for making this post and code can be
found here<br />
 The main idea for making this seamless is it could be easy to
switch gallery provider from picasa to whatever your favorite
web-photo gallery you use. Off course the difficulties you meet
depend on how well an interface the provider gives you, you could
end up in some tricky situations.</p>

<p><br />
 Okay let's get started. First of I've created the interfaces I've
so necessary for making a good web gallery. You are more than
welcome to give feedback if you think something are missing on one
these.</p>

<p>There exist three parts. A gallery which consists of one or more
photo albums. Next there off course a photo album which contain
some album information and one or more Images. Last off is the
image it self. So here are the three interfaces.</p>

<p>&nbsp;</p>

<pre class="brush:c#;">
 
public interface IGallery
  {
    String Name { get; }
    String Description { get; }
    int NumberOfAlbums { get; }
    IEnumerable Albums{get;}
    IGalleryAlbum GetAlbumFromId(string id);
  } 
</pre>

<pre class="brush:c#;">
 
public interface IGalleryAlbum
  {
    String Id { get; }
    String Name{ get; }
    String Description { get; }
    String Category { get; }
    IGalleryImage AlbumCoverImage { get; }
    uint NumberOfImages { get; }
    IEnumerable Images { get; }
  }
</pre>

<pre class="brush:c#;">
 
 public interface IGalleryImage
  {
    String Name { get; }
    String Url { get; }
    String Description { get; }
    String ThumbnailUrl { get; }
    Dictionary ExifData { get; }
  }
</pre>

<p><br />
 Again you are more than welcome to give feedback if you think
something is missing, keep in mind this is what I think is one a
good and simple image gallery should be able to provide of
information.<br />
 So now we have the interfaces in place lets go ahead an implement
them using the Picasa API.<br />
 This is a pretty simple task if keep a window open with the
documentation here is another link to the documentation<br />
 All I've used is the simple example provide at the documentation
page.<br />
 First of the gallery implementation this is simple</p>

<pre class="brush:c#;">
namespace PicasaGalleryModel
{
  public class PicasaGallery : IGallery
  {
    private PicasaService _service;
    private PicasaFeed _feed;


    private const string PICASA_SERVICE_NAME = "PicasaIGalleryModel";

    public PicasaGallery(string username)
    {
      Username = username;
    }

    public string Name
    {
      get
      {
        return Feed.Title.Text;
      }
    }

    public string Description
    {
      get { return ""; }
    }

    public int NumberOfAlbums
    {
      get { return Albums.Count(); }
    }

    public IEnumerable Albums
    {
      get
      {
        return InitializeGalleryAlbumFromPicasaFeed(); 
      }
    }

     public IGalleryAlbum GetAlbumFromId(string id)
     {
       return Albums.Where(g =&gt; g.Id == id).First();
     }

    private PicasaFeed Feed
    {
      get
      {
        if (_feed == null)
          _feed = RetrieveUserAlbumsFromPicasa();
        return _feed;
      }
    }

    private PicasaFeed RetrieveUserAlbumsFromPicasa()
    {
      AlbumQuery query = new AlbumQuery(PicasaQuery.CreatePicasaUri(Username));
      PicasaFeed feed = Service.Query(query);
      return feed;
    }

    private IEnumerable InitializeGalleryAlbumFromPicasaFeed()
    {
      foreach (PicasaEntry entry in Feed.Entries)
      {
        IGalleryAlbum album = new PicasaAlbum(entry,Service,Username);
        yield return album;
      }

    }

    private PicasaService Service
    {
      get
      {
        if(_service == null)
          _service = new PicasaService(PICASA_SERVICE_NAME);
        return _service;
      }
    }

    private void Logon()
    {
    }

    protected string Password
    {
      get;
      set;
    }

    protected string Username
    {
      get; set ;
    }
  }
}
</pre>

<p><br />
<br />
 DO note that the username is the logon name you use to logon to
picasa.<br />
 The implementation have some unused and unfinished function, when
I first the idea to this post it started as huge project where I
wanted security from picasa as well to be covered, in this
implementation.<br />
 Wow this class uses the IGalleryAlbum so let's move on to the
implantation of this.</p>

<pre class="brush:c#;">
namespace PicasaGalleryModel
{
  public class PicasaAlbum : IGalleryAlbum
  {
    private PicasaEntry _albumFeed;
    private PicasaFeed _imageFeed;
    private AlbumAccessor _ac;

    public PicasaAlbum(PicasaEntry feed,PicasaService service,string username)
    {
      AlbumFeed = feed;
      Service = service;
      Username = username;
    }

    public string Name
    {
      get { return AlbumAccessor.AlbumTitle; }
    }

    public string Description
    {
      get { return AlbumAccessor.AlbumSummary; }
    }

    public string Category
    {
      get { return "CAT-SET_STATIC"; }
    }

    public IGalleryImage AlbumCoverImage
    {
      get
      {
        PhotoQuery query = PhotoQueryFromUri(AlbumFeed.Id.AbsoluteUri);
        return BuildIGalleryImageFromPicasa(Service.Query(query)).First();
      }
    }

    private AlbumAccessor AlbumAccessor
    {
      get
      {
        if (_ac == null)
          _ac = new AlbumAccessor(AlbumFeed);
        return _ac;
      }
    }

    public uint NumberOfImages
    {
      get
      {
        
        return AlbumAccessor.NumPhotos;
      }
    }

    public IEnumerable Images
    {
      get 
      {
        return BuildIGalleryImageFromPicasa(ImageFeed);          
      }
    }

    private IEnumerable BuildIGalleryImageFromPicasa(PicasaFeed feed)
    {
      foreach (PicasaEntry entry in feed.Entries)
      {
        IGalleryImage image = new PicasaImage(entry);
        yield return image;
      }
    }

    public PicasaEntry AlbumFeed
    {
      get { return _albumFeed; }
      set { _albumFeed = value; }
    }

    public PicasaFeed ImageFeed
    {
      get
      {
        if(_imageFeed == null)
        {

          _imageFeed = Service.Query(PhotoQueryFromUri(PicasaImageUri()));
        }
        return _imageFeed;
      }
    }

    private string PicasaImageUri()
    {
      return PicasaQuery.CreatePicasaUri(Username, Id);;
    }

    private PhotoQuery PhotoQueryFromUri(string uri)
    {
      return new PhotoQuery(uri);
    }

    private PicasaService Service
    {
      get; set;
    }

    public String Id
    {
      get
      {
        return AlbumAccessor.Id;
      }
    }

    private string Username
    {
      get;
      set;
    }
  }
}

</pre>

<p><br />
<br />
 And now to the final part the Image implementation</p>

<pre class="brush:c#;">
namespace PicasaGalleryModel
{
  public class PicasaImage : IGalleryImage
  {

    private PhotoAccessor _photoAccessor;

    private Dictionary _exifData;

    public PicasaImage(PicasaEntry entry)
    {
      Entry = entry;
    }

    private PicasaEntry Entry
    {
      get;
      set;
    }

    public string Name
    {
      get
      {
        return PhotoAccessor.PhotoTitle;
      }
    }

    public string Url
    {
      get
      {
        return Entry.Media.Content.Attributes["url"].ToString();
      }
    }

    public string Description
    {
      get { return PhotoAccessor.PhotoSummary; }
    }

    public string ThumbnailUrl
    {
      get
      {
        return Entry.Media.Thumbnails[0].Attributes["url"].ToString();
      }
    }

    public Dictionary ExifData
    {
      get
      {
        if (_exifData == null)
          InitializeExifDataToDictionary();
        return _exifData;
      }
    }

    private void InitializeExifDataToDictionary()
    {
      _exifData = new Dictionary();
      _exifData.Add("Camera model", Entry.Exif.Model.Value);
      _exifData.Add("ISO", Entry.Exif.ISO.Value);
      _exifData.Add("Focal Length", Entry.Exif.FocalLength.Value);
      //_exifData.Add("Exposure", Entry.Exif.Exposure.Value);
      _exifData.Add("F Stop", Entry.Exif.FStop.Value);
      _exifData.Add("Flash", Entry.Exif.Flash.Value);
    }

    

    public PhotoAccessor PhotoAccessor
    {
      get
      {
        if(_photoAccessor == null)
          _photoAccessor = new PhotoAccessor(Entry);
        return _photoAccessor;
      }
    }

  }
}
</pre>

<p><br />
<br />
 Now with the model in place we can start to render out the
IGallery* stuff.<br />
 This is made so it should be easy to integrate into Umbraco hence
the MasterPage file.<br />
 The frontend stuff consist of the main gallery which loads in two
different controls depending on you are viewing a list of albums or
a list images in an album. The styling is left for you do, since
this is dependent on your website design. If you like a can In a
later post do this.<br />
 The main gallery<br />
<br />
 The .ascx page</p>

<p>&lt;%@ Page Language="C#" MasterPageFile="~/Gallery.master"
AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="Presentation._Default" %&gt;<br />
 &lt;%@ Import Namespace="Interfaces" %&gt;</p>

<p>&lt;asp:Content ID="head" ContentPlaceHolderID="head"
Runat="Server"&gt;<br />
 &lt;script type="text/javascript"
src="js/jquery.js"&gt;&lt;/script&gt;<br />
 &lt;script type="text/javascript"
src="js/jquery.lightbox-0.5.min.js"&gt;&lt;/script&gt;<br />
 &lt;script type="text/javascript"
src="js/InitLightbox.js"&gt;&lt;/script&gt;<br />
 &lt;link rel="stylesheet" type="text/css"
href="/CSS/jquery.lightbox-0.5.css" media="screen" /&gt;<br />
 &lt;/asp:Content&gt;<br />
<br />
 &lt;asp:Content ID="GalleryContent"
ContentPlaceHolderID="GalleryContent" Runat="Server"&gt;</p>

<p>&lt;div&gt;<br />
 My Gallery Test<br />
<br />
 &lt;asp:PlaceHolder ID="galleryContent" runat="server" /&gt;</p>

<p>&lt;/div&gt;<br />
 &lt;/asp:Content&gt;</p>

<p>&nbsp;</p>

<p><br />
 and the codepage</p>

<pre class="brush:c#;">
public partial class _Default : System.Web.UI.Page
  {
    private IGallery _gallery;
    public const string ALBUMID = "aid";

    protected void Page_Load(object sender, EventArgs e)
    {

      SetGalleryContent();
    }

   

    private void SetGalleryContent()
    {
      Control view;
      if (String.IsNullOrEmpty(AlbumId))
        view = LoadGalleryView;
      else
        view = LoadAlbumView;
      galleryContent.Controls.Add(view);
    }

    private IEnumerable GalleryAlbums
    {
      get
      {
        return Gallery.Albums;
      }
    }

    private Control LoadGalleryView
    {
      get
      {
        Control viewControl = LoadControl("~/GalleryView.ascx");
        GalleryView gallery = (GalleryView)viewControl;
        gallery.AlbumQueryString = ALBUMID;
        gallery.GalleryAlbums = GalleryAlbums;
        return viewControl;
      }
    }

    private Control LoadAlbumView
    {
      get
      {
        Control viewControl = LoadControl("~/AlbumView.ascx");
        AlbumView gallery = (AlbumView)viewControl;
        gallery.Images = CurrentAlbum.Images ;
        return viewControl;
      }
    }

    private IGalleryAlbum CurrentAlbum
    {
      get
      {
        return Gallery.GetAlbumFromId(AlbumId);
      }
    }
    private string AlbumId
    {
      get
      {
        return Request.QueryString[ALBUMID];
      }
    }

    private IGallery Gallery
    {
      get
      {
        if(_gallery == null)
          _gallery = new PicasaGallery("USERNAME_GOES_HERE");
        return _gallery;
      }
    }
  }
</pre>

<p><br />
 The List view of albums<br />
 Ascx page</p>

<p>&lt;%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="GalleryView.ascx.cs"
Inherits="Presentation.GalleryView" %&gt;<br />
 &lt;%@ Import Namespace="Interfaces"%&gt;</p>

<p>&lt;asp:Repeater runat="server" ID="AlbumeRepeater"
DataSource="&lt;%# GalleryAlbums %&gt;"&gt;<br />
 &lt;ItemTemplate&gt;<br />
 &lt;div class="AlbumCoverImage"&gt;<br />
 &lt;a href="&lt;%#
AlbumLink(((IGalleryAlbum)Container.DataItem).Id) %&gt;" &gt;<br />
 &lt;img src="&lt;%#
((IGalleryAlbum)Container.DataItem).AlbumCoverImage.ThumbnailUrl
%&gt;" alt="" /&gt;<br />
 &lt;/a&gt;<br />
 &lt;/div&gt;<br />
 &lt;div class="AlbumTitle"&gt;<br />
 &lt;a href="&lt;%#
AlbumLink(((IGalleryAlbum)Container.DataItem).Id) %&gt;" &gt;<br />
 &lt;%# ((IGalleryAlbum)Container.DataItem).Name %&gt;<br />
 &lt;/a&gt;<br />
 &lt;/div&gt;<br />
 &lt;div class="ImageCountInAlbum"&gt;<br />
 &lt;%# ((IGalleryAlbum)Container.DataItem).NumberOfImages
%&gt;<br />
 &lt;/div&gt;<br />
 &lt;div class="AlbumDescription"&gt;<br />
 &lt;%# ((IGalleryAlbum)Container.DataItem).Description%&gt;<br />
 &lt;/div&gt;<br />
<br />
 &lt;/ItemTemplate&gt;<br />
 &lt;/asp:Repeater&gt;</p>

<p>&nbsp;</p>

<p>Codepage</p>

<pre class="brush:c#;">
public partial class GalleryView : System.Web.UI.UserControl
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      AlbumeRepeater.DataBind();
    }

    public string AlbumLink(string albumId)
    {
      string url = String.Format("{0}{1}={2}", Request.RawUrl, AlbumQueryString, albumId);
      return url;
    }

    public string AlbumQueryString
    {
      get; set;
    }

    public IEnumerable GalleryAlbums
    {
      get;
      set;
    }

  }
</pre>

<p><br />
 And finally the list view of images in an album<br />
 Ascx page</p>

<p>&lt;%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="AlbumView.ascx.cs" Inherits="Presentation.AlbumView"
%&gt;<br />
 &lt;%@ Import Namespace="Interfaces"%&gt;<br />
 &lt;asp:Repeater ID="ImageRepeater" runat="server"
DataSource="&lt;%#Images %&gt;"&gt;<br />
 &lt;HeaderTemplate&gt;<br />
 &lt;ul id="Gallery"&gt;<br />
 &lt;/HeaderTemplate&gt;<br />
 &lt;ItemTemplate&gt;<br />
 &lt;li&gt;<br />
 &lt;a href="&lt;%# ((IGalleryImage)Container.DataItem).Url %&gt;"
class="lightbox" title="&lt;%#
ExifData((IGalleryImage)Container.DataItem)%&gt;"&gt;&lt;img
src="&lt;%# ((IGalleryImage)Container.DataItem).ThumbnailUrl %&gt;"
/&gt;&lt;/a&gt;<br />
<br />
 &lt;/li&gt;<br />
 &lt;/ItemTemplate&gt;<br />
 &lt;FooterTemplate&gt;<br />
 &lt;/ul&gt;<br />
 &lt;/FooterTemplate&gt;<br />
 &lt;/asp:Repeater&gt;</p>

<p>codefile</p>

<pre class="brush:c#;">
public partial class AlbumView : System.Web.UI.UserControl
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      ImageRepeater.DataBind();
    }

    public string ExifData(IGalleryImage image)
    {
      string exifData = "";
      foreach(string key in image.ExifData.Keys)
      {
        exifData += string.Format("{0} : {1}<br />
", key, image.ExifData[key]);
      }
      return exifData;
    }

    public IEnumerable Images
    {
      get;
      set;
    }
  }
</pre>

<p><br />
 The final part is using the jquery lightbox again you could switch
this to you own favorite gallery viewing service the lightbox for
jquery can be found here. I've extend this a bit so you can provide
a max image height and max image width, both are found in the
solution for this project.<br />
 And a service for my loyal readers, you can now download the
entire solution which contains all the above models
implementations, and all the other good stuff I've covered in this
post. Now you can get <a href="/media/3515/gallery.rar">HERE</a>,
Rememer to fill out your own Username</p>

<p>And now you can head over and see when this is integrated into
umbraco, i've done this for my site here is a like to my <a
href="/galleries.aspx" title="Galleries">gallery</a></p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>Simple GoogleMap made easy</title><link>http://www.istern.dk/blog/2010/2/23/simple-googlemap-made-easy.aspx</link><pubDate>Tue, 23 Feb 2010 12:57:03 GMT</pubDate><guid>http://www.istern.dk/blog/2010/2/23/simple-googlemap-made-easy.aspx</guid><content:encoded><![CDATA[ 
<p>I recently had to make a page showing different locations each
with it own little googlemap.</p>

<p>To make it easy to use i used jQuery to hook in a create the
googlemap from the html. The map generatet is a simple map with one
marker and centered on this marker. with an width and height set to
400px</p>

<p><img src="/media/3498/ss.jpg" width="376" height="461" alt="gmaps"/></p>

<p>So I used span tag html to set the settings need for generating
each googlemap.<br />
 I then use jQuery to look for a container that have one or multple
of theese maps inside and add a map to the specific "mapItem"</p>

<p>The html needed for one item is as shown below:</p>

<p>&nbsp;</p>

<pre class="brush:html;">
&lt;div class="Map"&gt;<br />
  &lt;span class="MapSettings"&gt;<br />
    &lt;span class="longtitude"&gt;Na;&lt;/span&gt;<br />
    &lt;span class="longtitude"&gt;Na&lt;/span&gt;<br />
    &lt;span class="mapId"&gt;Map0&lt;/span&gt;<br />
    &lt;span class="address"&gt;Pentia store kongensgade 66 copenhagen denmark&lt;/span&gt;<br />
    &lt;/span&gt;<br />
    &lt;div id="Map0" class="GoogleMap" style="width:400px; height:400px;"&gt;<br />
    &lt;/div&gt;<br />
  &lt;/div&gt;<br />
</pre>

<p>&nbsp;</p>

<p>To get it all to wok you of course need a googlemapApi key get
from <a
href="http://code.google.com/intl/da-DK/apis/maps/signup.html"
target="_blank">here</a></p>

<p>Here is the jquery file i used to hook in on document ready
function note if the longtitude and/or latitude isn't set i'l try
to and a marker to map from the address if that fails to you'll get
an invalide map.</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<pre class="brush:javascript">
jQuery(document).ready(function()
{
  buildMapsFromHTML();
}
)

/*****************

*  MAP SEETINGS  *

*****************/
var map;
var geocoder;
var zoomLevel = 14;
var mapIndex = 0;
 

/*****************

*  MAP FUNCTIONS *

*****************/
function buildMapsFromHTML(){
  var googleMaps = jQuery(".Map");
  var i;
  for (i = 0; i &lt; googleMaps.length; i++)
  {
    mapIndex = i;
    addMap(googleMaps[i],mapIndex);
  }
}

function addMap(mapSettings) {
  // GET SETTINGS FROM HTML
  var setting = jQuery(mapSettings).children(".MapSettings");
  var mapId = jQuery(setting).children(".mapId").html();
  var longtitude = jQuery(setting).children(".longtitude").html();
  var latitude = jQuery(setting).children(".latitude").html();
  var address = jQuery(setting).children(".address").html();

 
  if (latitude != "Na" || longtitude != "Na") {
    initializeMap(mapId);
    addMarkerToMap(longtitude, latitude);
    centerMap(longtitude, latitude);
  }
  else{
    generateMapFromAddress(address,mapId);
  }
}

function initializeMap(mapId) {
   map = new GMap2(document.getElementById(mapId));
}

function generateMapFromAddress(address,mapId) {
  var coordinate = cordinatesFromGoogle(address,mapId)
}

function cordinatesFromGoogle(address,mapId) {

  geocoder = new GClientGeocoder();

  geocoder.getLatLng(address, function(point) { 
  if(point) {
    var longtitude = point.lng().toFixed(5)
    var latitude = point.lat().toFixed(5)
    initializeMap(mapId);
    addMarkerToMap(longtitude, latitude);
    centerMap(longtitude, latitude);
  }
  })
}

function addMarkerToMap(longtitude, latitude) {
  var point = new GLatLng(latitude, longtitude);
  var marker = new GMarker(point);
  map.addOverlay(marker);
}

function centerMap(longtitude, latitude) {
   var point = new GLatLng(latitude, longtitude);
    map.setCenter(point, zoomLevel);
}
</pre>

<p>&nbsp;</p>

<p>So an example html to bind it all together could look like
this:</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<pre class="brush:html;">
&lt;html&gt;
&lt;head&gt;
&lt;script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=true_or_false&amp;key=localhost type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="googlMaps.js"&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div class="Map"&gt;
  &lt;span class="MapSettings"&gt;
    &lt;span class="longtitude"&gt;Na&lt;/span&gt;
    &lt;span class="latitude"&gt;Na&lt;/span&gt; 
    &lt;span class="mapId"&gt;Map0&lt;/span&gt; 
    &lt;span class="address"&gt;store kongensgade 66 copenhagen denmark&lt;/span&gt; 
  &lt;/span&gt;
    &lt;div id="Map0" class="GoogleMap" style="width:400px; height:400px;"&gt;
    &lt;/div&gt;
 &lt;/div&gt;
 
 &lt;div class="Map"&gt;
  &lt;span class="MapSettings"&gt;
    &lt;span class="longtitude"&gt;Na&lt;/span&gt;
    &lt;span class="latitude"&gt;Na&lt;/span&gt; 
    &lt;span class="mapId"&gt;Map1&lt;/span&gt; 
    &lt;span class="address"&gt;store kongensgade 66 copenhagen denmark&lt;/span&gt; 
  &lt;/span&gt;
    &lt;div id="Map1" class="GoogleMap" style="width:400px; height:400px;"&gt;
    &lt;/div&gt;
 &lt;/div&gt;
 
 &lt;/body&gt;
&lt;/html&gt;


</pre>

<p>If no longtitude or/and latitude is set i gets the marker from
the address.<br />
 and Na should be used to say that you dont have those values.
Offcourse it could be extended to specify which kind of map and so
on. This could be set in the settings as well togehter with
zoomlevel and so on.</p>

<p>remember to set the googlemap key to your domain</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>Adding captcha "Recaptcha Umbraco Blog"</title><link>http://www.istern.dk/blog/2010/1/22/adding-captcha-recaptcha-umbraco-blog.aspx</link><pubDate>Fri, 22 Jan 2010 10:26:03 GMT</pubDate><guid>http://www.istern.dk/blog/2010/1/22/adding-captcha-recaptcha-umbraco-blog.aspx</guid><content:encoded><![CDATA[ 
<p>So after i my self got spammed by a lot of robots on my blog i
browsed the internet to find an easy way to add captcha for the
comment part of my blog.</p>

<p>So i found the easiest way to do was using recaptcha, which can
be found here <a href="http://recaptcha.net"
target="_blank">recaptcha.net</a>. So before we start head over
there and create an account.</p>

<p>Step 1:</p>

<p>Create recaptcha.net account&nbsp; <a
href="http://recaptcha.net" target="_blank">recaptcha.net</a></p>

<p>&nbsp;</p>

<p>Step 2:</p>

<p>Download the .Net package containing the recaptcha.dll</p>

<p>&nbsp;</p>

<p>Step 3:</p>

<p>Download from you site frmBlogComment.ascx placed in
siteroot/usercontrols</p>

<p>&nbsp;</p>

<p>Step4:</p>

<p>Edit frmBlogComment.ascx</p>

<p>add the following lines</p>

<p>&nbsp;</p>

<pre class="brush: c#">
&lt;%@ Import Namespace="Recaptcha"&gt;
&lt;%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha"&gt;

void btnSubmit_Click1(object sender, EventArgs args)
{
  if (recaptcha.IsValid)
  {
     btnSubmit_Click(sender,args);
  }
}

</pre>

<p>These lines should be right after the "control tag" "&lt;%@
Control ...... %&gt;"</p>

<p>&nbsp;</p>

<p>Futher down you can now add the recaptcha usercontrol</p>

<p>&lt;recaptcha:RecaptchaControl<br />
 ID="recaptcha"<br />
 runat="server"<br />
 PublicKey=...<br />
 PrivateKey=....<br />
 /&gt;</p>

<p>&nbsp;</p>

<p>ofcourse with your privatekey and publickey..</p>

<p>&nbsp;</p>

<p>Step 5:</p>

<p>Upload recaptcha.dll to your webroot/bin</p>

<p>Upload the newly edited&nbsp; frmBlogComment.ascx to you
webroot/usercontrols/</p>

<p>&nbsp;</p>

<p>And you should be all done and no more bots should spam your
blog I hope.</p>

<p>This post is for them that dont want to recompile umbraco, it
would be a much better solution to add an reference to the
recaptcha.dll</p>

<p>&nbsp;</p>
]]></content:encoded></item><item><title>Encrypting and signing  Mail in .Net part 5/5 (Encrypting the content and sending the mail)</title><link>http://www.istern.dk/blog/2010/1/19/encrypting-and-signing--mail-in-net-part-55-(encrypting-the-content-and-sending-the-mail).aspx</link><pubDate>Tue, 19 Jan 2010 12:40:28 GMT</pubDate><guid>http://www.istern.dk/blog/2010/1/19/encrypting-and-signing--mail-in-net-part-55-(encrypting-the-content-and-sending-the-mail).aspx</guid><content:encoded><![CDATA[ 
<p style="display:none;">Topic: How to encrypt and sign mail c#.
Signed mail in c#, signing c#, c# send encrypted mail, signed
encrypted mail c#, S/MIME messages,Sending encrypted email - C#</p>

<p>Final part in the serie c# encrypting mail.</p>

<p>&nbsp;</p>

<p>So now we got the content build and signed. Now what is left to
do i encrypting the content.</p>

<p>In this post we have a look at how the structure of the content
should just before it is encrypted, and how to encrypt the
content.</p>

<p><a href="/blog/2010/1/12/encrypting-and-signing-mail-in-net-part-15.aspx"
title="Encrypting and signing Mail in .Net part 1/5">Link to part
1</a>, <a href="/blog/2010/1/13/encrypting-and-signing--mail-in-net-part-25-(retrieving-certificats).aspx"
title="Encrypting and signing Mail in .Net part 2/5 (retrieving certificats)">
part 2</a>, <a href="/blog/2010/1/16/encrypting-and-signing-mail-in-net-part-35-(building-the-content---with-attachments).aspx"
title="Encrypting and signing Mail in .Net part 3/5 (Building the content - with attachments)">
part 3</a>, <a href="/blog/2010/1/18/encrypting--and-signing-mail-in-net-part-45-(signing-the-content).aspx"
title="Encrypting and signing Mail in .Net part 4/5 (Signing the content)">
part 4</a></p>

<p>To encrypt the content I will use the GetCert method that we did
in part 4 of this series.</p>

<p>As with the signing part we will split this encryption into two
bits. adding boundary to the content and encrypting part.</p>

<p>First the encrypting part:</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<pre class="brush: c#">
 public byte[] DoEncrypt(string message, X509Certificate2 encryptionCertificates)
           {
               byte[] messageBytes = Encoding.ASCII.GetBytes(message);

               EnvelopedCms envelopedCms = new EnvelopedCms(new ContentInfo(messageBytes));

               CmsRecipient recipients = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, encryptionCertificates);

               envelopedCms.Encrypt(recipients); 

               return envelopedCms.Encode();
           }

</pre>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>With this function done we can now ready the content for
encryptions. We add a simple boundary to the content and specifies
what type the innner boundary is of. Important that if you skipped
the signing part that you change this accordingly to match the type
of you content.</p>

<p>Here is the code for encrypting and sending the mail:</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<pre class="brush: c#">
 public void encrypt(string content)
       {
           MailMessage message = new System.Net.Mail.MailMessage();
           string encryptedContentType = "application/x-pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"";
           string signatureBoundry2 = "--PTBoundry=3";
           StringBuilder fullUnencryptedMessageBuilder = new StringBuilder();
           fullUnencryptedMessageBuilder.Append("Content-Type: ");
           fullUnencryptedMessageBuilder.Append("multipart/signed; ");
           fullUnencryptedMessageBuilder.Append(" boundary=\"");
           fullUnencryptedMessageBuilder.Append(signatureBoundry2);
             fullUnencryptedMessageBuilder.Append("\"; protocol=\"application/x-pkcs7-signature\"; micalg=SHA1; ");
           
           fullUnencryptedMessageBuilder.Append("\r\n");
           fullUnencryptedMessageBuilder.Append("Content-Transfer-Encoding: ");
           fullUnencryptedMessageBuilder.Append(TransferEncoding.SevenBit);
           fullUnencryptedMessageBuilder.Append("\r\n\r\n");
           fullUnencryptedMessageBuilder.Append(content); 

           string fullUnencryptedMessage = fullUnencryptedMessageBuilder.ToString();

           byte[] encryptedBytes = DoEncrypt(fullUnencryptedMessage, GetCert());

           MemoryStream stream = new MemoryStream(encryptedBytes);
           AlternateView view = new AlternateView(stream, "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
           message.AlternateViews.Add(view);
           message.To.Add("youremail@yourdomain.com");
        
           message.From = new MailAddress("someone@yourdomain.com");
           message.Subject = "TEST";
           SmtpClient smtp = new SmtpClient("smtp.yourdomain.com");
           smtp.Send(message);

       
       }
</pre>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>This function also sends out the mail you might wanna spilt this
up to seperate methods. And do remember to give valide email
adresses and a sane smtphost.</p>

<p>Now lets have a look at the result:</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><img src="/media/2987/mailbui5l_500x129.jpg"  width="500"  height="129" alt="mailbui5l"/></p>

<p>Yes there is a warning with the signature but rember in part 1
where did a selfsigned certificate this is the problem, but you cal
always just accept the signature as trusted in your outlook.</p>

<p>Okay so how doesn't the content that we build look like just
before it is encrypted ?</p>

<p>If hightligthe the different steps we done in this series.</p>

<p>&nbsp;</p>

<p><img src="/media/2994/mailbui34l_535x423.jpg"  width="535"  height="423" alt="mailbui34l"/></p>

<p><a href="/media/2994/mailbui34l.jpg">link to image</a></p>

<p>Also note the diffenrent boundary references from one part to
underlaying content part.</p>

<p><img src="/media/2982/mailbuil_500x395.jpg"  width="500"  height="395" alt="mailbuil2"/></p>

<p>you can find the code file for this project in the download
section <strong><a href="/media/3005/default.txt">here is a
link.</a></strong></p>

<p>Rememer to change email smtp host and serial for certificat</p>

<p>Note you should implement all the explained methods in nice
class's that wraps all this functionality into one simple class.
The code file you can download is constructed as a simple file so i
would be easier to explain howto encrypt and sign emails. It is not
intended to be used for production purposes.</p>

<p>Finished you now know ho to encrypt and sign mails with c#.</p>

<p>c# encrypting and signing mail</p>
]]></content:encoded></item></channel></rss>
