David
David

Reputation: 85

How to filter in QBO using ampersand

When using Intuit.Ipp.Data.Qbo.CustomerQuery I can add a Name filter to query the database for a specific company name which works. But if the customer name includes an ampersand, for example B&H, it throws a "401 Unauthorized" error.

After reviewing the question and attempted answers at Intuit.Ipp.Data.Qbo.CustomerQuery query with & in the name I tried xml encoding the filter value to "B&H" as suggested by Jarred which produced the same error. I also tried to call the API directly with the following code but it also produces the same error (unless I change my filter value to a customer without the &)

    public List<Intuit.Ipp.Data.Qbo.Customer> GetQboCustomers(DataServices dataServices)
    {
        StringBuilder requestXML = new StringBuilder();
        StringBuilder responseXML = new StringBuilder();

        string requestBody = "Filter=NAME :EQUALS: B&amp;H";

        HttpWebRequest httpWebRequest = WebRequest.Create(dataServices.ServiceContext.BaseUrl + "customers/v2/" + dataServices.ServiceContext.RealmId) as HttpWebRequest;
        httpWebRequest.Method = "POST";
        httpWebRequest.ContentType = "application/x-www-form-urlencoded";
        httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest));
        requestXML.Append(requestBody);
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] content = encoding.GetBytes(requestXML.ToString());
        using (var stream = httpWebRequest.GetRequestStream())
        {
            stream.Write(content, 0, content.Length);
        }
        HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
        using (Stream data = httpWebResponse.GetResponseStream())
        {
            Intuit.Ipp.Data.Qbo.SearchResults searchResults = (Intuit.Ipp.Data.Qbo.SearchResults)dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(new StreamReader(data).ReadToEnd());
            if (searchResults.Count > 0)
            {
                return ((Intuit.Ipp.Data.Qbo.Customers)searchResults.CdmCollections).Customer.ToList();
            }
            else
            {
                return new List<Intuit.Ipp.Data.Qbo.Customer>();
            }
        }

    }

    protected string GetDevDefinedOAuthHeader(HttpWebRequest webRequest)
    {

        OAuthConsumerContext consumerContext = new OAuthConsumerContext
        {
            ConsumerKey = consumerKey,
            ConsumerSecret = consumerSecret,
            SignatureMethod = SignatureMethod.HmacSha1,
            UseHeaderForOAuthParameters = true

        };

        consumerContext.UseHeaderForOAuthParameters = true;
        //URIs not used
        OAuthSession oSession = new OAuthSession(consumerContext, "https://www.example.com",
        "https://www.example.com",
        "https://www.example.com");


        oSession.AccessToken = new TokenBase
        {
            Token = accessToken,
            ConsumerKey = consumerKey,
            TokenSecret = accessTokenSecret
        };

        IConsumerRequest consumerRequest = oSession.Request();
        consumerRequest = ConsumerRequestExtensions.ForMethod(consumerRequest, webRequest.Method);
        consumerRequest = ConsumerRequestExtensions.ForUri(consumerRequest, webRequest.RequestUri);
        if (webRequest.Headers.Count > 0)
        {
            ConsumerRequestExtensions.AlterContext(consumerRequest, context => context.Headers = webRequest.Headers);
            if (webRequest.Headers[HttpRequestHeader.ContentType] == "application/x-www-form-urlencoded")
            {
                formParameters.Add("Filter", "NAME :EQUALS: B&amp;H");
                consumerRequest = consumerRequest.WithFormParameters(formParameters);
            }
        }

        consumerRequest = consumerRequest.SignWithToken();
        return consumerRequest.Context.GenerateOAuthParametersForHeader();
    }

I have simplified the above code so that you can easily identify what query value I am trying to pass. If B&amp;H is changed to BH then the query executes without an issue so it isn't an authorization issue.

Upvotes: 0

Views: 362

Answers (1)

Peter Lavelle
Peter Lavelle

Reputation: 1484

Please see an example here showing how to encode the filter values and calculate the signature. https://gist.github.com/IntuitDeveloperRelations/6024616

Upvotes: 2

Related Questions