An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set. trying to consuming a webservice

13,790

Solution 1

BaseAddress is there so that you can make all the calls relative to the the BaseAddress. It works, you just need to know some of the idiosyncrasies of BaseAddress Why is HttpClient BaseAddress not working?

But your problem is that you are instantiating a new HttpClient in each method.

static async Task<Uri> CreateCustomerAsync(Customer customer)
{
    HttpClient client = new HttpClient();
    //you never set the BaseAddress 
    //or the authentication information
    //before making a call to a relative url!
    HttpResponseMessage response = await client.PostAsJsonAsync("api/customers/1?output_format=JSON", customer);
    response.EnsureSuccessStatusCode();

    // return URI of the created resource.
    return response.Headers.Location;
}

A better way would be to wrap the HttpClient call in a class and it up in the constructor, then share it in any of your methods

    public WrapperClass(Uri url, string username, string password, string proxyUrl = "")
    {
        if (url == null)
            // ReSharper disable once UseNameofExpression
            throw new ArgumentNullException("url");
        if (string.IsNullOrWhiteSpace(username))
            // ReSharper disable once UseNameofExpression
            throw new ArgumentNullException("username");
        if (string.IsNullOrWhiteSpace(password))
            // ReSharper disable once UseNameofExpression
            throw new ArgumentNullException("password");
        //or set your credentials in the HttpClientHandler
        var authenticationHeaderValue = new AuthenticationHeaderValue("Basic",
            // ReSharper disable once UseStringInterpolation
            Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password))));

        _httpClient = string.IsNullOrWhiteSpace(proxyUrl)
            ? new HttpClient
            {
                DefaultRequestHeaders = { Authorization = authenticationHeaderValue },
                BaseAddress = url
            }
            : new HttpClient(new HttpClientHandler
            {
                UseProxy = true,
                Proxy = new WebProxy
                {
                    Address = new Uri(proxyUrl),
                    BypassProxyOnLocal = false,
                    UseDefaultCredentials = true
                }
            })
            {
                DefaultRequestHeaders = { Authorization = authenticationHeaderValue },
                BaseAddress = url
            };

        _httpClient.DefaultRequestHeaders.Accept.Clear();
        _httpClient.DefaultRequestHeaders.AcceptEncoding.Clear();
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

    public async Task<Member> SomeCallToHttpClient(string organizationId)
    {
        var task = await _httpClient.GetStringAsync(<your relative url>));

        return JsonConvert.DeserializeObject<SomeType>(task,
            new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver()});
    }

Solution 2

I bet you need the complete url address. The url is not relative to the caller when using HttpClient.

static async Task<Uri> CreateCustomerAsync(Customer customer)
{
   HttpClient client = new HttpClient();
   HttpResponseMessage response = await client.PostAsJsonAsync("http://www.fullyqualifiedpath.com/api/customers/1?output_format=JSON", customer);
   response.EnsureSuccessStatusCode();

   // return URI of the created resource.
   return response.Headers.Location;
}
Share:
13,790

Related videos on Youtube

Zero One
Author by

Zero One

Updated on June 04, 2022

Comments

  • Zero One
    Zero One almost 2 years

    I am trying to Consume a Web Service using HttpClient in .NET and after i did all steps mentioned in msdn

    o Get the following exception : An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.

    here is my class

    public class Customer
    {
        public int id { get; set; }
        public string id_default_group { get; set; }
        public string id_lang { get; set; }
        public string newsletter_date_add { get; set; }
        public string ip_registration_newsletter { get; set; }
        public string last_passwd_gen { get; set; }
        public string secure_key { get; set; }
        public string deleted { get; set; }
        public string passwd { get; set; }
        public string lastname { get; set; }
        public string firstname { get; set; }
        public string email { get; set; }
        public string id_gender { get; set; }
        public string birthday { get; set; }
        public string newsletter { get; set; }
        public string optin { get; set; }
        public string website { get; set; }
        public string company { get; set; }
        public string siret { get; set; }
        public string ape { get; set; }
        public string outstanding_allow_amount { get; set; }
        public string show_public_prices { get; set; }
        public string id_risk { get; set; }
        public string max_payment_days { get; set; }
        public string active { get; set; }
        public string note { get; set; }
        public string is_guest { get; set; }
        public string id_shop { get; set; }
        public string id_shop_group { get; set; }
        public string date_add { get; set; }
        public string date_upd { get; set; }
        public string reset_password_token { get; set; }
        public string reset_password_validity { get; set; }
    
    }
    
    class Program
    {
    
        static void ShowProduct(Customer customer)
        {
            Console.WriteLine($"Email: {customer.email}\tFirst Name: {customer.firstname}");
        }
    
        static async Task<Uri> CreateCustomerAsync(Customer customer)
        {
            HttpClient client = new HttpClient();
            HttpResponseMessage response = await client.PostAsJsonAsync("api/customers/1?output_format=JSON", customer);
            response.EnsureSuccessStatusCode();
    
            // return URI of the created resource.
            return response.Headers.Location;
        }
        static void Main()
        {
            RunAsync().Wait();
        }
        static async Task RunAsync()
        {
            NetworkCredential hd = new NetworkCredential("INHFTLZLMLP1TUTJE7JL9LETCCEW63FN", "");
            HttpClientHandler handler = new HttpClientHandler {Credentials = hd };
            HttpClient client = new HttpClient(handler);
    
            client.BaseAddress = new Uri("http://localhost:8080/newprestashop/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                try
                {
    
                    Customer customer = new Customer();
                    var url = await CreateCustomerAsync(customer);
                    // Get the product
                    customer = await GetProductAsync(url.PathAndQuery);
                    ShowProduct(customer);
    
    
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
    
                Console.ReadLine();
            }
    
        static async Task<Customer> GetProductAsync(string path)
        {
            Customer customer = null;
            HttpClient client = new HttpClient();
            HttpResponseMessage response = await client.GetAsync(path);
            if (response.IsSuccessStatusCode)
            {
                customer = await response.Content.ReadAsAsync<Customer>();
            }
            return customer;
        }
    
    }
    

    }

    • Mitch Stewart
      Mitch Stewart almost 7 years
      Are you sure your web service is up and running at localhost:8080? I would launch the web api project and add a break point at the start of the method (index) of the controller (newprestashop) you are trying to hit. Then, make your call from your client.
    • Zero One
      Zero One almost 7 years
      i test in post man it work great
  • Zero One
    Zero One almost 7 years
    works great the exception is gone but it gives another " Response status code does not indicate success: 401 (Unauthorized)."
  • Ross Bush
    Ross Bush almost 7 years
    That means you need to authenticate prior to making your api call. The endpoint was reached and rejected due to lack of authorization.
  • Fran
    Fran almost 7 years
    Your authorization problem is the same problem as your BaseAddress one. you instantiate HttpClient and never set the values. See my answer.
  • Ross Bush
    Ross Bush almost 7 years
    I would actually give the answer to @Fran. I solved your immediate problem, however, his answer solves with a better overall solution.