Wednesday, September 22, 2010

upload file into sharepoint 2007 (copy.asmx)

There are many ways to do it:

  1. Customised web services
  2. Out-of-the-box web service (copy.asmx)
  3. WebDAV
Advantages of using Customised web services:
  • Ease of uploading (through personalised codes)
  • Ability to do many fine tuning (such as permissions, etc)
Disadvantages of using Customised web services:
  • Not all SharePoint owners are comfortable with customised webservices running on their server
Advantages of using Out-of-the-box web service (copy.asmx):
  • Using Microsoft "supported" API
  • No need to fear if the next service pack is going to screw up all the pre-patch programs
Disadvantages of using Out-of-the-box web service (copy.asmx):
  • Limited No way to set permissions of files
Advantages of using WebDAV:
  • Very easy to implement
Disadvantages of using WebDAV:
  • Unable to set any metadata
I had a recent job to do a migration from File System -> SharePoint Document Library. A short summary of what happened: 

I was told to migrate everything over with the same file names, permissions, taxonomy (folder structures), etc.

Initially, i chose to use SharePoint OOTB web service to do all the above, as i know that i can use it to create folders, upload items, set metadata, etc. Until i hit a problem: I can't fricking set the permissions. After a lot of negotiation with my stakeholders, there's only 2 choice for me (without breaching their microsoft gold support clauses). Deploy a customized web service written by me or skip the whole permission idea (they have to do it manually using cheap interns). Lucky for me, they chose to skip the permission thing, so i proceed to continue with the whole project with user-friendly user interface using just the Web Service of SharePoint. Another advantage of using it is, you can use it anywhere as long as you can achieve a connection to the SharePoint and File System, you do not need to be running on either servers.

I am still tweaking the project source codes for some eye candies before my next new assignment begins.

And for the copy.asmx to be consumed, you only have to do this:

public string UploadFile(string sourceFilePath, string destinationUrl)
{
            string msg = string.Empty;
            Copy c = new Copy(); 
            c.Url = this.spURL + "/_vti_bin/copy.asmx";
            Authenticate(c);

            byte[] myBinary = File.ReadAllBytes(sourceFilePath); 
            string[] destinationUrlColl = { destinationUrl };

            FieldInformation info1 = new FieldInformation(); 
            info1.DisplayName = "Title"; 
            info1.InternalName = "Title"; 
            info1.Type = FieldType.Text; 
            info1.Value = "new title"; 

            FieldInformation[] info = { info1 }; 
            CopyResult resultTest = new CopyResult(); 
            CopyResult[] result = { resultTest }; 

            try 
            { 
                //When creating new content use the same URL in the SourceURI as in the Destination URL argument

                c.CopyIntoItems(destinationUrl, destinationUrlColl, info, myBinary, out result); 
                 if (result[0].ErrorMessage != null)
                 {
                     msg = "Error: " + result[0].ErrorMessage;
                 }
                 else
                 {
                     msg = "Success";
                 }
            } 
            catch (Exception ex) 
            { 
                //TODO: logging & handling
            }
            return msg;
}

I written a simple authentication method to do the authentication properly -> Authenticate(c);

internal CookieContainer AuthenticateFBA()
        {
            CookieContainer cookies = new CookieContainer();
            using (GSPAuthenticationWS.Authentication authSvc = new GSPAuthenticationWS.Authentication())
            {
                authSvc.Url = this.spURL + "/_vti_bin/authentication.asmx";
                authSvc.CookieContainer = new System.Net.CookieContainer();     //create a new cookie container
                authSvc.AllowAutoRedirect = true;

                //set the FBA login information
                try
                {
                    GSPAuthenticationWS.LoginResult result = authSvc.Login(this.spAdminId, this.spAdminPw);
                    if (result.ErrorCode == GSPAuthenticationWS.LoginErrorCode.NoError)
                    {
                        CookieCollection cookieColl = authSvc.CookieContainer.GetCookies(new Uri(authSvc.Url));
                        //Get the specific cookie which contains the security token
                        cookies.Add(cookieColl[result.CookieName]);
                    }
                }
                catch (WebException wex)
                {
                    throw new NotImplementedException("Specified Sharepoint server is not FBA-enabled");
                }
                return cookies;
            }
        }

        internal NetworkCredential AuthenticateIWA()
        {
            return new NetworkCredential(this.spAdminId, this.spAdminPw, this.spAdminDomain);
        }

        private void Authenticate(SoapHttpClientProtocol SoapProtocol)
        {
            if (this.isFBAEnabled)
            {
                SoapProtocol.CookieContainer = AuthenticateFBA();
            }
            else
            {
                ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
                ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                {
                    //Here we can write code for implementing client side validation.
                    // This anonymous function is a call back function which is called once the SSL validation completes on WebServer.
                    return true;
                };
                SoapProtocol.Credentials = AuthenticateIWA();
            }
        }

A neat way to authenticate through the web service for both Form Based authentication and Integrated Windows authentication :)


Tuesday, September 14, 2010

iOS 4.1 development

I'm currently picking up a little on Objective-C to do some iOS development, for school project though. Since i have a MacBook (late 2009), apple developer account (free) and iPhone 3GS, it should not be that hard.. (i assumed)

I had very little C and C++ experience and knowledge, i'm just a hello world-level developer for both languages. That didn't stop me from downloading the 2.9 GB Xcode IDE and iOS4.1 SDK and try to write my first Hello World.

Followed a few guides like this and this, it wasn't that hard to print a hello world using the Interface Builder:
Just follow the guides step-by-step and try to grasp a few of the IDE (which is rather different from Visual Studio, NetBeans & SharePoint Designer)





After messing around with a few UIKit controls, i met a problem of not able to retract the keyboard on the simulator. Went around some forums and found that Apple gave a very good tutorial: UICatalog, which included most, if not all of the controls available in the API.

However, when i loaded the xcodeproj file, the compiler keep giving me the message: "Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain"
You can bring the build results up by pressing: command+shift+B










After a few attempts to search around the net for the solution, many suggested setting up Keychain Access (windows equivalent of the certificate manager) so that you have Apple Worldwide Developer Relations Certification, and the iPhone developer certificate, iPhone distributor certificate (if you want to put apps into iTunes), there are lots of things to do and pay (for distributing), but hey, i'm just trying to mess around with iOS 4.1, i'm not yet ready to go through all these.

I tried to set the code signing options under the project settings, but it still doesn't let me compile and run the simulator. Then for no reason, i looked at the build results window and saw that the build option was targetted for "device" instead of "simulator". I didn't change it to device (which requires you to do the above certificate signing set-up), it was the default setting, i changed it to "Simulator" then pressed command+B and everything went well, finally.

I'll be messing around more with Xcode and hope to be able to produce something and decide if i'll sign up for a distributor package with Apple @ US$99/yr. Stay tuned.

Thursday, August 5, 2010

rants of a singaporean male

Being a singaporean is tough, a singaporean male is tougher. (No doubt there are nations where, just being a citizen is punishing enough).

To strive for excellence but to give up social life and attention for your loved ones, or to be glad with what you have currently and spend the rest of your life like any other person? I'm going through a hard time, trying to get a degree, serving my nation (NSmen overseas training), working full time in a very harsh environment, appease my parents to make them not worry about me, to cherish the love of my life that i found recently.

I do not know how long i can last before i burn out, i really hope that i do not end up becoming like the sort of people that i've been bitching about.

2 years of my prime-time was spent on protecting my nation, i had to delay my degree programme and i have 2 years lesser working experience than my female peers... not to mention the major influx of Foreign Talents are making my sector very competitive. To start planning for family seems so faraway with my current remuneration, housing price are sky-high and COE (a certificate which you must buy if you want to own a car in Singapore)... looking at friends that come from wealthy family makes me feel so inferior and helpless.

This is one of the rare posts whereby it's got nothing to do with technical stuff, sorry if you are a fellow singaporean male and feel the same (if you don't already feel the same :)), for non singaporeans or maybe females that reads my blog. Be glad if you are not in the same situation as many of us, this is rarely a place for me to rant. But all these emotions have to go somewhere and this place seem to be a decent one.

Wednesday, July 28, 2010

WSE 3.0 extreme latency

We had a legacy .NET web-service that uses WSE 3.0. We are the service provider and we have an intermediate authentication server as well as the consumer. We had intermittent mysterious socket time out exceptions.

A thorough network snoop was conducted across 4 network teams (we span across 2 intranet and 2 WAN domains). Everything was healthy with <10ms latency between hops.

It was puzzling and a stroke of genius came by and we decided to check the inputtrace.webinfo and outputtrace.webinfo (default logging configs). Nothing special about it except for the size. Monthly scheduled jobs archival results in file size in excess of 600mb. Some team members had argued that logging mechanism should be asynchronous and should not have any influence on the response SOAP. There's no harm trying to flush out the logs and archive and do a re-test. Sure enough everything was back to < 0.5s

Our corrective action was to increase the frequency of the archival from monthly to weekly.

Wednesday, July 21, 2010

Gridview grouping

I've worked with SPGridView quite a bit lately and know that grouping is achievable, i thought that Gridview being the superclass of SPGridview, it should support grouping as well. I was wrong. My girlfriend had a requirement to group a set of data based on their type. A mock set of the data involved:


Product A - Type A
Product B - Type A
Product C - Type B
Product D -Type B
Product E - Type C
Product F - Type D


My first move was to take a look at the DAL (Data access layer) to see how the objects are related, in order for me to plan on grouping it. They are returned as generic dataset, so i had to create some simple POCO (Plain Old C# Objects), i prefer to work with strongly-typed grids :)


After retrieving the the data, i've modified the DAL to return an IList of the POCO instead of DS.


With the data retrieval and formatting done, all i have to do now is to bind it to a gridview and set the group by option. A little googling, i found a custom gridview which allow grouping:
ZNetControls

Read a little on the page and from the author's documentation, it seem simple enough.


  1. I created an ObjectDataSource that hooks up with the DAL GetAllBindableObjects() as the selectmethod. 
  2. Added the library (ZNetControls) into my VS and added the ZNetGridview into the page
  3. Added the grouping type: DataKeyNames="Category"
Ran the page and i get this:


Pretty easy to implement :)