cancel
Showing results for 
Search instead for 
Did you mean: 

Calling Alfresco Web Services from C#

osho
Champ in-the-making
Champ in-the-making
Hi,

I am starting this topic to share my experience of calling Alfresco Web Services from .Net, the problems which you may face and the solutions.

I first started with scratch. I created a C# project and added a Web reference to AuthenticationService (authentication-service.wsdl) , and VersioningService (VersioningService.wsdl).
Then I wrote following lines of code
            WindowsApplication1.AuthenticationService.AuthenticationService asvc = new WindowsApplication1.AuthenticationService.AuthenticationService();            AuthenticationResult ar = asvc.startSession("admin", "admin");‍‍

It worked fine. Examining ar showed the token returned by Alfresco.
I then wrote the following lines
           VersioningService vs = new VersioningService();            string repID = ("xyz");            string docID = ("abc");            string docRefId = docID;            bool b = vs.checkOut(repID, ref docRefId);‍‍‍‍‍‍‍
I was expecting an exception to be generated for giving invalid parameters, but the exception generated was about target service is null. It seems VersioningService is not exposed at URL/alfresco/api/VersioningService.
I then tried to add reference to RepositoryService (repository-service.wsdl ). Visual Studio reported a problem:
The document was understood, but it could not be processed. The WSDL document contains links that could not be resolved.

The solution was to remove the  nillable attributes in cml.xsd files. After doing that, it was able to add the reference. I then wrote the following lines
            RepositoryService rs = new RepositoryService();            rs.Credentials = asvc.Credentials;            Store[] stores = rs.getStores();‍‍‍
The exception which got generated was about Unauthorization. It was simple to figure out the cause, I was not passing in the security token, it was hard to figure out how to pass that. I was stuck.

I then googled and found out that there is demo project called dotNet2 for calling Alfresco APIs from .Net. I downloaded the same and tried to build it. It turned out that there was a missing reference to Microsoft.Web.Services3 assembly. Solution was to install MS WSE 3. So well and good.
I tried building the solution and there was a problem:

Error 1 The best overloaded method match for 'WebServiceFactory.addSecurityHeader(Microsoft.Web.Services3.WebServicesClientProtocol)' has some invalid arguments
Error 2 Argument '1': cannot convert from 'Alfresco.RepositoryWebService.RepositoryService' to 'Microsoft.Web.Services3.WebServicesClientProtocol'

I tried google to find out the solution for this, and I got one but it didn't work. A close observation revealed that addSecurityHeader was expecting Microsoft.Web.Services3.WebServicesClientProtocol object the service objects which we were passing were derived from SoapHttpClientProtocol class. I found that Microsoft.Web.Services3.WebServicesClientProtocol itself derives from SoapHttpClientProtocol, so I just let the web services class derive from Microsoft.Web.Services3.WebServicesClientProtocol and it worked!!

Then I tried to call getStores() method of RepositoryWebService and I again encountered exception. There was some problem in class instantiation from the returned response. Close observation again revealed the problem. The StoreEnum of RepositoryWebService was defined like this
    public enum StoreEnum {        /// <remarks/>        workspace,        /// <remarks/>        versionStore,        /// <remarks/>        user,        /// <remarks/>        search,        /// <remarks/>        http,        /// <remarks/>        system,    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I extended this enum to look like this

    public enum StoreEnum {        /// <remarks/>        workspace,        /// <remarks/>        versionStore,        /// <remarks/>        user,        /// <remarks/>        search,        /// <remarks/>        http,        /// <remarks/>        system,        archive,        avm,    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And after doing this, the call succeeded  Smiley Happy
Now my task was to test checking out of a selected file and getting a previous version of a selected file. After many hit and trials, I got it working and here is the reference code (I added  private AuthoringService authoringService; to Browse class)

This is the code for Checking Out a selected file:
        private void CheckOut_Click(object sender, EventArgs e)        {            ListViewItem item = listViewBrowse.SelectedItems[0];            if (item != null)            {                ResultSetRowNode node = item.Tag as ResultSetRowNode;                if (node != null)                {                    if (node.type.Contains("folder") == false)                    {                        // Create the reference for the node selected                        Alfresco.AuthoringWebService.Store spacesStore2 = new Alfresco.AuthoringWebService.Store();                        spacesStore2.scheme = Alfresco.AuthoringWebService.StoreEnum.workspace;                        spacesStore2.address = "SpacesStore";                        Alfresco.AuthoringWebService.Reference reference = new Alfresco.AuthoringWebService.Reference();                        reference.store = spacesStore2;                        reference.uuid = node.id;                        // Lets try to check out                        Alfresco.AuthoringWebService.Predicate predicate = new Alfresco.AuthoringWebService.Predicate();                        predicate.Items = new Object[] { reference };                        Alfresco.AuthoringWebService.ParentReference pr = new Alfresco.AuthoringWebService.ParentReference();                        pr.store = spacesStore2; ;                        pr.uuid = this.currentReference.uuid;                        pr.associationType = Constants.ASSOC_CONTAINS;                        pr.childName = Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, item.Text);                        this.authoringService.checkout(predicate, pr);                    }                    else                    {                         // show message that a folder has been selected                    }                }            }        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And this is the code for getting the original version of a file
        private void GetOriginalVersion_Click(object sender, EventArgs e)        {            Alfresco.RepositoryWebService.Store[] stores = this.repoService.getStores();            Alfresco.RepositoryWebService.Store vStore = stores[3]; // from data, I found out that this is for Versioned store            ListViewItem item = listViewBrowse.SelectedItems[0];            if (item != null)            {                ResultSetRowNode node = item.Tag as ResultSetRowNode;                if (node != null)                {                    if (node.type.Contains("folder") == false)                    {                        // Create the reference for the node selected                        Alfresco.AuthoringWebService.Store spacesStore2 = new Alfresco.AuthoringWebService.Store();                        spacesStore2.scheme = Alfresco.AuthoringWebService.StoreEnum.workspace;                        spacesStore2.address = "SpacesStore";                        Alfresco.AuthoringWebService.Reference reference = new Alfresco.AuthoringWebService.Reference();                        reference.store = spacesStore2;                        reference.uuid = node.id;                        VersionHistory VH = this.authoringService.getVersionHistory(reference);                        int i = 0;                        char[] temp = new char[1];                        temp[0] = '0';                        string versions = new string(temp);                        Alfresco.AuthoringWebService.Version first;                        foreach (Alfresco.AuthoringWebService.Version version in VH.versions)                        {                            if (i == 0)                                first = version;                            versions += version.label + (";") + version.id.uuid + (";");                        }                        {                            // Create the reference for the node selected                            Alfresco.ContentWebService.Store spacesStore3 = new Alfresco.ContentWebService.Store();                            spacesStore3.scheme = Alfresco.ContentWebService.StoreEnum.versionStore;                            spacesStore3.address = vStore.address;                            Alfresco.ContentWebService.Reference reference1 = new Alfresco.ContentWebService.Reference();                            reference1.store = spacesStore3;                            reference1.uuid = VH.versions[VH.versions.GetUpperBound(0)].id.uuid;                            // Lets try and get the content                            Alfresco.ContentWebService.Predicate predicate = new Alfresco.ContentWebService.Predicate();                            predicate.Items = new Object[] { reference1 };                            Content[] contents = this.contentService.read(predicate, "{http://www.alfresco.org/model/content/1.0}content");                            Content content = contents[0];                            if (content.url != null && content.url.Length != 0)                            {                                string url = content.url + "?ticket=" + AuthenticationUtils.Ticket;                                webBrowser.Url = new Uri(url);                            }                        }                    }                    else                    {                       // show message that a folder has been selected                    }                }            }        }    }}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I hope this post helps you. If you also found similar or new issues, please post under this thread, so that new comers can have a list of all the problems and solutions at the same place.

-osho
16 REPLIES 16

nkunta
Champ in-the-making
Champ in-the-making
Thank you so much for sharing your experience with calling Alfresco web services, this was very helpful. I could not solve the issues as I did not follow few of the instructions.

Error 1 The best overloaded method match for 'WebServiceFactory.addSecurityHeader(Microsoft.Web.Services3.WebServicesClientProtocol)' has some invalid arguments
Error 2 Argument '1': cannot convert from 'Alfresco.RepositoryWebService.RepositoryService' to 'Microsoft.Web.Services3.WebServicesClientProtocol'
A close observation revealed that addSecurityHeader was expecting Microsoft.Web.Services3.WebServicesClientProtocol object the service objects which we were passing were derived from SoapHttpClientProtocol class. I found that Microsoft.Web.Services3.WebServicesClientProtocol itself derives from SoapHttpClientProtocol, so I just let the web services class derive from Microsoft.Web.Services3.WebServicesClientProtocol and it worked!!

Can you please let me know how you solved the above error by writing the exact lines of code.

Also where exactly did you add the following code:
RepositoryService rs = new RepositoryService();
            rs.Credentials = asvc.Credentials;
            Store[] stores = rs.getStores();

Sorry for asking too many questions. Any help will be greatly appreciated.

osho
Champ in-the-making
Champ in-the-making
Hi nkunta,

I assume that you have installed MS WSE 3.

To resolve the build issue :
In WebServiceFactory.cs, chnage the definition of addSecurityHeader(SoapHttpClientProtocol service) to
       
private static void addSecurityHeader(Microsoft.Web.Services3.WebServicesClientProtocol service)‍
and let RepositoryService derive from Microsoft.Web.Services3.WebServicesClientProtocol, rather than from SoapHttpClientProtocol (in alfresco-dotNet-0.2Beta\Alfresco\Web References\RepositoryWebService\Reference.cs)
public partial class RepositoryService : Microsoft.Web.Services3.WebServicesClientProtocol‍
Do this for all the services.

For your second question:
I was not aware of dotnet2 demo project, so I was trying things from scratch. In the process, I created a C# project and added the said lines of code there, just to test the things. When I got dotnet2 project, I discarded my own project and started trying dotnet2 to get up and working.

Hope it helps,

-Osho

nkunta
Champ in-the-making
Champ in-the-making
Thank you for your response. I figured out the issue in a hard way  Smiley Happy

I am still having one issue, though… I am getting an error that scheme and address are missing in the repositorywebservice in GetStores. I am not sure if I am having invalid wsdl files. Can you tell where I can find the wsdl files and also the dotnet2 project in Alfresco web site.

Thank You in advance.

osho
Champ in-the-making
Champ in-the-making
Try modifying StoreEnum of RepositoryWebService like this

public enum StoreEnum {        /// <remarks/>        workspace,        /// <remarks/>        versionStore,        /// <remarks/>        user,        /// <remarks/>        search,        /// <remarks/>        http,        /// <remarks/>        system,        archive,        avm,    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I do not have a direct link to dotNet2, but little bit of googling will surely help. I have seen people asking for a link to dotNet2 in this forum also. After you find dotNet2, please provide the link here as well.
dotNet2 is a very helpful in getting started with Alfresco WS from .Net

-Osho

nkunta
Champ in-the-making
Champ in-the-making
I still did not find the source code for dotnet2 which i believe is the code that calls the web services.
I am still not sure why this is not working for me. I still think I have wrong wsdl files. When I search for the files in Alfresco site, I get an error that the site is forbidden even after I log in.

The following is my problem now. My website works fine on local host and I have permission issues when I deploy to development web site. When I strong name the dll's I get the error
    "System.Security.SecurityException: That assembly does not allow partially trusted callers.". Stack Trace information has the following info:
    ClsRepositoryRead…ctor(logonstructure ..) in Repository
    system.web.ui.control.onload(EventsArgs e +99)
    and other web.ui.control messages…
    Content_wiki_wiki_aspx.processRequest (HTTPContext Context) in app_web_fxsds
Based on these errors, I added AllowPartiallyTrustedCallersAttribute in the assembly and referenced it from the code. Now, I am not able to compile my code. I get following errors:
    The type 'Alfresco.RepositoryWebService.Store' is defined in an assembly that is not referenced. You must add a reference to assembly 'Alfresco, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1169d……   
    Alfresco.RepositoryWebService.Store' does not contain a definition for 'scheme'   
    Alfresco.RepositoryWebService.Store' does not contain a definition for 'address'
I added the code suggested by Osho but with no luck. Any help will be greatly appreciated.

jon318
Champ in-the-making
Champ in-the-making
I also want to know what's going on?

osho
Champ in-the-making
Champ in-the-making
Hi nkunta,

I googled again and found the link to dotNet2 project.

Find the link at:
http://sangosthi.blogspot.com/2009/04/calling-alfresco-web-services-from-c.html

Now you can head start with it.

-Osho

osho
Champ in-the-making
Champ in-the-making
You can also find modified dotnet2 demo project there. This project additionally allows to do a Check out and Get latest version of a file.

-Osho

nkunta
Champ in-the-making
Champ in-the-making
I am still not sure if I am missing something. The biggest issue for me now is I get trust issue errors when connecting to Alfresco from the development website. When I set the APTCA attribute in dotnet2 project then I get stores.scheme error.