Pages

Search This Blog

Showing posts with label Web service. Show all posts
Showing posts with label Web service. Show all posts

Monday, June 17, 2013

Send Large data with SharePoint Webservice


When ever you need to send lots of lots of data in WCF REST service using custom SharePoint MultipleBaseAddressWebServiceHostFactory then you will encounter following error 

(400) HTTP Bad Request


When you look into service trace you will find the actual root cause of this issue is that the data sent is not supported by default and its failing internally in deserialize process

<ExceptionType>System.ServiceModel.Dispatcher.NetDispatcherFaultException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:ADXML. The InnerException message was 'There was an error deserializing the object of type System.String. The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.'.  Please see InnerException for more details.</Message>
<StackTrace>

Now if you try to override the settings in web.config then web service will complain about multiple settings for the same end point because factory it self creates the dynamic end points so web.service changes can't be used unless you remove the factory class and do it conventional way.

So what is the solution :

Its easy that we need to just extend two classes

Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory 
Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHost


 public class CustomMultipleBaseAddressWebServiceHostFactory : Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory
    {
        protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new CustomMultipleBaseServiceHost(serviceType, baseAddresses);
        }

      
    }

    public class CustomMultipleBaseServiceHost : Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHost
    {
        public CustomMultipleBaseServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
        }


        protected override void OnOpening()
        {
            base.OnOpening();

            System.Diagnostics.Debug.Assert(false);

            foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
            {
                Binding binding = endpoint.Binding;
                if (binding is WebHttpBinding)
                {
                    var web = binding as WebHttpBinding;
                    web.MaxBufferSize = Int32.MaxValue;
                    web.MaxReceivedMessageSize = Int32.MaxValue;
                }
                var myReaderQuotas = new XmlDictionaryReaderQuotas();
                myReaderQuotas.MaxStringContentLength = Int32.MaxValue;
                binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
            }
        }
    }

Now if you see we can make the changes to any parameters like maxBufferSize or MaxrecievedMessageSize at the time of opening of channel.

Now instead of using default Microsoft class in the svc file we will use our custom dll reference. Deploy your solution. DO an IISRESET and you will be able to transmit huge data now :)

<%@ ServiceHost Language="C#" 
Service="Custom.Assembly.Classname,$SharePoint.Project.AssemblyFullName$" 
CodeBehind="CustomClass.cs"
Factory="CustomMultipleBaseAddressWebServiceHostFactory, $SharePoint.Project.AssemblyFullName$"  %> 

Monday, December 26, 2011

Accessing SharePoint List using REST - WCF based Data Service

In this post I will tell you how a SharePoint List can be accessed through the REST (Representational State Transfer) WCF based Data service. In this example I have a list name “LearningList, which is accessed and shown in a Data Grid. Using this I have also shown how to update the same. To have the source code to the example Click here.

Before you can proceed further with the example verify that the WCF Data services are installed in your environment, as it does not comes with the SharePoint installation. To verify the install enter the following URL to your browser: http://<server name>/_vti_bin/ListData.svc

Otherwise to download it Click here.

CODE SNIPPET
  • Create a new Custom List and name it “LearningList”.
  •  Create the fields as shown in the image

  • Create a new Visual Studio 2010 --> Visual C# --> Windows  --> Windows Forms Application. And provide the name for the project (for example: RestSharepointList).

  • Now Right click the References and click on the Add Service Reference. Enter the following URL:  http://<server name>/_vti_bin/ListData.svc and click Go.  Visual Studio will search and return the number of lists, which will include the example list.

  • Provide the Namespace for the service (for example: RestListService )
  • Add the Lists Data Grid to the Designer by clicking on the Data -->Show data Sources -->LearningList (drag this to the designer which will be added as the Data Grid).


  • Re-Design the form as shown in the image.


  • On the Form_Load add the code 


  • · I have added three buttons 
    •   Add: This is to add the new Item in the List.

    • Refresh: This is to refresh the list so as to see the current added item in the List.

    • Clear: This is to clear the textboxes.
  • Full Code from the code behind
namespace RestSharePointList
{
    public partial class Form1 : Form
    {
        //Create a Proxy of the service
        RESTListService.LearningDataContext objContext = new LearningDataContext(new Uri("http://br-pc-350:2789/_vti_bin/ListData.svc"));

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //provide the credentials for the proxy to access the SharePoint List
            objContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            //Create a Linq Query to get the data from the list using the proxy
            var listData = from p in objContext.LearningList
                           select p;
            //You can also filter the data from the List by modifing the LINQ Query

            //Bind the DataGrid with the data retreived from the List
            this.learningListBindingSource.DataSource = listData;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            //Emptying the Text Boxes
            txtAuthor.Text = "";
            txtInStock.Text = "";
            txtPrice.Text = "";
            txtTitle.Text = "";
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            //create a List object and assign the values
            LearningListItem objItem = new LearningListItem();
            objItem.Author = txtAuthor.Text;
            objItem.Price = txtPrice.Text;
            objItem.InStock = txtInStock.Text;
            objItem.Title = txtTitle.Text;

            try
            {
                //Add the Items to the List
                objContext.AddToLearningList(objItem);
                objContext.SaveChanges();
                MessageBox.Show("Item added Successfully");
            }
            catch(Exception ex)
            {
                MessageBox.Show("Error Occured: " + ex.Message);
            }

        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {

            //provide the credentials for the proxy to access the SharePoint List
            objContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            //Create a Linq Query to get the data from the list using the proxy
            var listData = from p in objContext.LearningList
                           select p;
            //You can also filter the data from the List by modifing the LINQ Query

            //Bind the DataGrid with the data retreived from the List
            this.learningListBindingSource.DataSource = listData;
        }
    }
}

  •  Now press F5 and the output will look something like this.
Happy Coding..!!!