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.