none
Call custom BCS methods from a webpart

    Question

  • Hello, I've been developng an application in Sharepoint that calls a WCF webservice that is configured in the BCS datastore, the basic readspecific, readall, update and delete methods work properlly, but I need to be able to call from a webpart a method that returns a list based on some input parameters that are determined at runtime. The parameters are read in a webpart from the user profile and need to be passed as an argument to the webservice who then proesses them and returns a result set that has to be shown either on a MOSS List or a gridview or any kind of control.

    I've been searching online but truth be told I haven't been able to understand how it works. I created and added the service (witch is hosted on the same server as sharepoint) following this post from MSDN http://msdn.microsoft.com/en-us/library/gg318616.aspx only I didn't enable the claims awareness couse it's not neded; and I followed this article http://msdn.microsoft.com/en-us/library/ff769953.aspx to try and create my webpart but so far I haven't been successfull. 

    The WCF Service is defined as follows:

     

      [ServiceContract]
      public interface IServicesSVI
      {
        [OperationContract]
        Evento GetEventById(int id);
    
        [OperationContract]
        List<Evento> GetEventsByKeyword(string rawKeywords);
    
        [OperationContract]
        void SaveEvent(Evento newEvento);
    
        [OperationContract]
        void DeleteEvent(Evento evento);
    
        [OperationContract]
        List<Evento> GetAllEvents();
      }
    

     

    And the method's List<Evento> GetEventsByKeyword(string rawKeywords); where the class Evento is defined as a [DataContract].

    I'd really apreciate help here since it's the final part of the project i'm working on and it's the most important part, what i need is how to call

    the GetEventsByKeyword method from the webpart.

     

    Thankes

     

    Mauricio Dominguez Diaz del Castillo


    Sunday, May 29, 2011 3:45 AM

All replies

  • Hi Mauricio,

    You said the web part didn't work. But did you get any error message?

    The second article you posted describes how to call a method from BDC service:
    try
    {
    using (new Microsoft.SharePoint.SPServiceContextScope(
    SPServiceContext.GetContext(SPContext.Current.Site)))
    {
    // Get the BDC service and metadata catalog.
    BdcService service =
    SPFarm.Local.Services.GetValue<BdcService>(String.Empty);
    IMetadataCatalog catalog =
    service.GetDatabaseBackedMetadataCatalog(
    SPServiceContext.Current);

    // Get the entity by using the specified name and namespace.
    IEntity entity =
    catalog.GetEntity(EntityNamespace, EntityName);
    ILobSystemInstance LobSysteminstance =
    entity.GetLobSystem().GetLobSystemInstances()[0].Value;

    // Create an Identity based on the specified Customer ID.
    Identity identity = new Identity(keyword in this case);

    // Get a method instance for the SpecificFinder method.
    IMethodInstance method =
    entity.GetMethodInstance("GetEventsByKeyword",
    MethodInstanceType.SpecificFinder);

    // Execute the Specific Finder method to return the
    // customer data.
    IEntityInstance iei =
    entity.FindSpecific(identity, LobSysteminstance);

    // Display the data for the returned customer in the UI.
    Title.Text = iei["Title"] != null ?
    iei["Title"].ToString() : string.Empty;

    }
    }
    catch (Exception ex)
    {
    //Handle error

    }
    }


    However, please note a SpecificFinder returns exactly one entity instance.

    In this case, I would suggest you to modify the GetEventsByKeyword to return only one Event instead of Events. If the method returns Events, only the first Event will be got. It is by design.

    Thanks,
    Jinchun Chen


    Jin Chen - MSFT
    Friday, June 03, 2011 10:21 AM
  • Hi Jin,thankes for the reply and yes, I'd seen the second post and how it shows the use of a SpecificFinder method, the problem is that I need to get a collection of objects since it's what the processing in my WCF service needs to retun acording to my Buissnes Logic.

    Updating on my current status, y am trying to use the GenericInvoker an this far I've already returned successfully the items from my method, the problem now is that the GenericInvoker returns an object of Object class and i'm not able to cast it to the original Data type since the classes are contained in the WCF service and exposed only as a DataContract.

     

    Thanke you

    Friday, June 03, 2011 9:08 PM
  • Hi Mauricio,

    You should define the origiral Data type again in the custom web part.

    Thanks,
    Jinchun Chen


    Jin Chen - MSFT
    Saturday, June 04, 2011 5:44 AM
  • Hi Jin,

     

    Doing this wouldn't defeat the purpouse of having an architecture

     

    Thanks,

    Mauricio Dominguez Diaz del Castillo

    Saturday, June 04, 2011 7:06 PM
  • Here's a sample that calls a model's specific finder method.

    Scot

    using System;
    using System.Reflection;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;

    //Reference to Microsoft.SharePoint.dll
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    using Microsoft.SharePoint.BusinessData;
    using Microsoft.SharePoint.BusinessData.Runtime;
    using Microsoft.SharePoint.BusinessData.SharedService;
    using Microsoft.SharePoint.BusinessData.MetadataModel;
    using Microsoft.BusinessData.Infrastructure;

    //Reference to Microsoft.BusinessData.dll
    using Microsoft.BusinessData;
    using Microsoft.BusinessData.MetadataModel;
    using Microsoft.BusinessData.Runtime;
    using Microsoft.BusinessData.MetadataModel.Collections;

    namespace ExecuteSpecificFinder
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {

                    if (args.Count() != 6)
                        throw new Exception("Useage: ExecuteFinder SiteCollectionUrl, LobSystemInstance, EntityName, EntityNamespace, SpecificFinderMethodInstance, EntityInstanceIdentifier");

                    string siteCollectionUrl = args[0];
                    string lobSystemInstance = args[1];
                    string entityName = args[2];
                    string entityNamespace = args[3];
                    string specificFinderMethodInstance = args[4];
                    string entityInstanceIdentifier = args[5];

                    using (SPSite site = new SPSite(siteCollectionUrl))
                    {
                        //Connect to the BDC Service Application proxy
                        BdcService service = SPFarm.Local.Services.GetValue<BdcService>();

                        if (service == null)
                            throw new Exception("No BDC Service Application found.");

                        //Connect to metadata catalog
                        DatabaseBackedMetadataCatalog catalog = service.GetDatabaseBackedMetadataCatalog(SPServiceContext.GetContext(site));

                        //Get entity
                        IEntity ect = catalog.GetEntity(entityNamespace, entityName);

                        //Get LobSystem
                        ILobSystem lob = ect.GetLobSystem();

                        //Get LobSystemInstance
                        ILobSystemInstance lobi = lob.GetLobSystemInstances()[lobSystemInstance];

                        //Get Method Instance
                        IMethodInstance mi = ect.GetMethodInstance(specificFinderMethodInstance, MethodInstanceType.SpecificFinder);

                        //Get Parameters
                        IParameterCollection parameters = mi.GetMethod().GetParameters();

                        //Set Parameters
                        object[] arguments = new object[parameters.Count];
                        arguments[0] = entityInstanceIdentifier;

                        //Execute
                        ect.Execute(mi, lobi, ref arguments);

                        //Display
                        PropertyInfo[] props = arguments[1].GetType().GetProperties();
                        PropertyInfo prop = props[0];
                        SqlDataReader reader = (SqlDataReader)(prop.GetValue(arguments[1], null));

                        if (reader.HasRows)
                        {
                            while (reader.Read())
                            {
                                Console.WriteLine(reader.GetString(3) + " " + reader.GetString(5));
                            }
                        }

                    }
                }
                catch (Exception x)
                {
                    Console.WriteLine(x.Message);
                }
            }
        }
    }


    Author, Professional Business Connectivity Services
    Author, Inside SharePoint 2010 Blog, www.shillier.com
    Twitter, @ScotHillier
    SharePoint Trainer, Critical Path Training
    Monday, June 06, 2011 10:27 AM
  • Hi Jin,

     

    I tried out to cast to the data type present on my webservice but I get a "Unable to cast object of type 'BCSServiceProxy.Evento[]' to type 'InvestigacionBOL.ObjetoNegocio.Evento[]'." exception... any ideas?

    Thursday, June 09, 2011 12:51 AM