Sunday, December 16, 2012

Working with Office components on the web server


Anyone who has tried using office components in a web application can testify that it’s a pain setting it up.

Just recently we ran into an issue setting it up on a Win2k8 R2 server. Just to ensure I can fall back upon something if I ever get caught out again, I am listing the steps here.

If the application Pool is running under a service account, then it needs to have access on the following:

  1. The following registry keys:
a.       HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID\{000xxx-xxx-xxx}
b.      HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{000xxx-xxx-xxx }
2.       This folder:
 %windir%\SysWoW64\config\systemprofile\Desktop
This folder no longer exists in Win2k8 – not sure why it was taken out but it is something that the office components need to create the files.
3.       Permissions in Component Services
a.       The permissions added in both section were as below:
·         Under Access Permissions à Edit Default à Add service account and check "Local Access" checkbox
·         Under "Launch and Activation permissions" à Edit Default à Add service account and check "Local Launch" and "Local activation" checkboxes




Saturday, December 1, 2012

Simple Ftp Client

I had to put together an ftp client to test some application today - nothing much just needed the listing and upload features.

Below is what i came up with:

public class FtpClient
    {
        private const string FtpProtocolHeader = "ftp://";
        private const string EscapedForwardSlash = "%2f";

        private string requestUriString;
        public string RequestUriString
        {
            get { return requestUriString; }
        }

        private string UserName { get; set; }

        private SecureString Password { get; set; }

        private FtpClient() { }

        public FtpClient(string uri, string userId, string password)
        {
            requestUriString = BuildUri(uri);
            UserName = userId;
            char[] passwordChars = password.ToCharArray();
            Password = new SecureString();
            foreach (char c in passwordChars)
                Password.AppendChar(c);
        }

        private static string BuildUri(string uri)
        {
            if (!System.Uri.IsWellFormedUriString(uri, UriKind.Absolute))
                throw new ArgumentException("Parameter is not well formed", "uri");

            if (!uri.StartsWith(FtpProtocolHeader, StringComparison.OrdinalIgnoreCase))
                uri = FtpProtocolHeader + uri;

            if (!uri.EndsWith("/", StringComparison.OrdinalIgnoreCase))
                uri += "/";
            return uri;
        }

        public FtpClient(string uri, string userId, SecureString password)
        {
            requestUriString = BuildUri(uri);
            UserName = userId;
            Password = password;
        }

        public IEnumerable DirectoryListing()
        {
            return DirectoryListing(null);
        }

        
        public IEnumerable DirectoryListing(string targetDir)
        {
            if (!string.IsNullOrWhiteSpace(targetDir))
            {
                BuildRequestUri(targetDir);
            }
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(RequestUriString);
                request.Proxy = null;

                request.Method = WebRequestMethods.Ftp.ListDirectory;
                request.Credentials = new NetworkCredential(UserName, Password);

                using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        if (responseStream == null)
                            return null;
                        List result;
                        using (var reader = new StreamReader(responseStream))
                        {
                            result = new List();

                            while (!reader.EndOfStream)
                            {
                                result.Add(reader.ReadLine());
                            }
                        }
                        return result;
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void BuildRequestUri(string targetDir)
        {
            Debug.Assert(requestUriString != null, "requestUriString != null");
            if (!String.IsNullOrWhiteSpace(targetDir) && targetDir.StartsWith("/"))
            {
                targetDir = targetDir.Substring(1);
                requestUriString += string.Format("{0}{1}", EscapedForwardSlash, targetDir);
            }

        }

        
        public bool UploadFile(string fileSourcePath, string targetDir)
        {
            if (!File.Exists(fileSourcePath))
            {
                throw new ArgumentException("File path is invalid", "fileSourcePath");
            }
            string fileName = Path.GetFileName(fileSourcePath);
            BuildRequestUri(targetDir);
            try
            {
                // Get the object used to communicate with the server.
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(RequestUriString + fileName);

                request.UseBinary = true;
                request.Proxy = null;
                request.Method = WebRequestMethods.Ftp.UploadFile;

                // use the credentials
                request.Credentials = new NetworkCredential(UserName, Password);
                byte[] fileContent = File.ReadAllBytes(fileSourcePath);
                request.ContentLength = fileContent.Length;

                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(fileContent, 0, fileContent.Length);
                }

                FtpWebResponse response = (FtpWebResponse)request.GetResponse();

                return (response.StatusCode == FtpStatusCode.ClosingData);
            }
            catch
            {
                throw;
            }
        }
    }
Ran into an issue setting the root directory and it took me a while to understand it. From MSDN:

The URI may be relative or absolute. If the URI is of the form "ftp://contoso.com/%2fpath" (%2f is an escaped '/'), then the URI is absolute, and the current directory is /path. If, however, the URI is of the form "ftp://contoso.com/path", first the .NET Framework logs into the FTP server (using the user name and password set by the Credentials property), then the current directory is set to /path.


Of course, it doesn't do much at the moment, I intend to add some more commands to it soon. I also want to try out an async upload option.

Thursday, September 13, 2012

Start of Week

Needed to find the first day of the next week for a given date. I thought there might be an in-built method to do this, but I didn't see anything.

So I wrote these extension methods - one that uses the CurrentCulture and one that can work on a predefined day of the week.
public static class DateTimeExtensions
{
    public static DateTime GetNextWeekStartDate(this DateTime dt, 
                                                DayOfWeek weekStartDay)
    {
        var difference = weekStartDay - dt.DayOfWeek;
        if (difference < 0)
            difference += 7;
        return dt.AddDays(weekStartDay - dt.DayOfWeek + 7);
    }

    public static DateTime GetNextWeekStartDate(this DateTime dt)
    {
        CultureInfo ci = Thread.CurrentThread.CurrentCulture;
        DayOfWeek weekStartDay = ci.DateTimeFormat.FirstDayOfWeek;
        return GetNextWeekStartDate(dt, weekStartDay);
    }
}

But I hate adding the 7 there. I am sure this can be done in  a more elegant way. Another time perhaps...

Monday, September 10, 2012

Design Patterns


What are Design Patterns?
Design Patterns are general and reusable templates or solutions to solve common problems. It is not an algorithm but a usual pattern which can be used to design a solution to the problem.

History
The term is taken from a book by Christopher Alexander – a regular "buildings" architect. 

In software development these ideas were initially published in the book - Design Patterns: Elements of Reusable Object-Oriented Software. The authors of the book - Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides are together often called the Gang of Four (GoF).

Why do they matter?
Design patterns are well accepted solutions to existing software development problems and provide templates to define systems with good OO design qualities. The design patterns provide a common language between developers to explain complex scenarios.

Pattern Organization
Patterns are organized in an ever increasing list (as new patterns are discovered).
  1. Creational
    1.   Factory
    2. Builder
    3. Etc...
  2. Structural
    1. Decorator
    2. Etc.
  3. Behavioral
  4. Security
  5. Etc.
Further reading: Design Patterns