4

I need to shorten my links using bitly in C#. Is there any nuget package for this? Can some one provide me code for that so that I can use that.

torvin
  • 6,515
  • 1
  • 37
  • 52
Dalvir Singh
  • 423
  • 3
  • 11
  • 25

6 Answers6

11

Check out https://www.nuget.org/packages/BitlyAPI/ or just make your own call to the bit.ly api. The api is very easy to use and work with.

public string Shorten(string longUrl, string login, string apikey)
{
    var url = string.Format("http://api.bit.ly/shorten?format=json&version=2.0.1&longUrl={0}&login={1}&apiKey={2}", HttpUtility.UrlEncode(longUrl), login, apikey);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try
    {
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
            JavaScriptSerializer js = new JavaScriptSerializer();
            dynamic jsonResponse = js.Deserialize<dynamic>(reader.ReadToEnd());
            string s = jsonResponse["results"][longUrl]["shortUrl"];
            return s;
        }
    }
    catch (WebException ex)
    {
        WebResponse errorResponse = ex.Response;
        using (Stream responseStream = errorResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            // log errorText
        }
        throw;
    }
}

You can get your login and apikey from bit.ly by going to this link https://bitly.com/a/your_api_key

Gericke
  • 2,109
  • 9
  • 42
  • 71
devfunkd
  • 3,164
  • 12
  • 45
  • 73
  • Sometimes I get error: ***403 - RATE_LIMIT_EXCEEDED***. And `ApiKey` is _deprecated_. – Kiquenet Sep 27 '18 at 14:46
  • @Kiquenet I'm just stumbling on this comment and you are right. I'm working on a new version API V4 that should be out this week.I'm the author of the linked nuget package. – Jeff Feb 12 '20 at 01:04
11

I had problems with the Nuget package Bitly.Net so I implemented @devfunkd's solution above. However I still had the same problems on Azure see this related link so I had to develop a slightly different solution.

My solution uses a fixed OAuth Token for authentication, as suggested by bit.ly support. It worked on Azure and has the advantage that it is not depreciated like the older 'login'/'apiKey'. In case this is useful to someone here is the code, based on @devfunkd but updated to:

  • Use the fixed OAuth token for validation.
  • Use the bit.ly's V3 API, which has a nicer json format.
  • It uses Json.NET json deserialiser, which I mainly use.
  • I made it async as most of the rest of my system is async.

Note that in the code the field _bitlyToken should contain a token created by going to this page. The _logger variable holds some sort of logger so that errors are not lost.

public async Task<string> ShortenAsync(string longUrl)
{
    //with thanks to @devfunkd - see https://stackoverflow.com/questions/31487902/nuget-package-for-bitly-to-shorten-the-links

    var url = string.Format("https://api-ssl.bitly.com/v3/shorten?access_token={0}&longUrl={1}",
            _bitlyToken, HttpUtility.UrlEncode(longUrl));

    var request = (HttpWebRequest) WebRequest.Create(url);
    try
    {
        var response = await request.GetResponseAsync();
        using (var responseStream = response.GetResponseStream())
        {
            var reader = new StreamReader(responseStream, Encoding.UTF8);
            var jsonResponse = JObject.Parse(await reader.ReadToEndAsync());
            var statusCode = jsonResponse["status_code"].Value<int>();
            if (statusCode == (int) HttpStatusCode.OK)
                return jsonResponse["data"]["url"].Value<string>();

            //else some sort of problem
            _logger.ErrorFormat("Bitly request returned error code {0}, status text '{1}' on longUrl = {2}",
                statusCode, jsonResponse["status_txt"].Value<string>(), longUrl);
            //What to do if it goes wrong? I return the original long url
            return longUrl;
        }
    }
    catch (WebException ex)
    {
        var errorResponse = ex.Response;
        using (var responseStream = errorResponse.GetResponseStream())
        {
            var reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            var errorText = reader.ReadToEnd();
            // log errorText
            _logger.ErrorFormat("Bitly access threw an exception {0} on url {1}. Content = {2}", ex.Message, url, errorText);
        }
        //What to do if it goes wrong? I return the original long url
        return longUrl;
    }
}

I hope that helps someone.

Community
  • 1
  • 1
Jon P Smith
  • 2,391
  • 1
  • 30
  • 55
1

The other answers are great but the example code will no longer work https://www.nuget.org/packages/BitlyAPI/4.0.0 has been updated so you can use it or look at it's code in github https://github.com/doublej42/BitlyAPI

Jeff
  • 4,622
  • 2
  • 27
  • 40
1
    public static async Task<string> ShortenUrl(string url)
    {
        string _bitlyToken = "<my token>";
        HttpClient client = new HttpClient();

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
            "https://api-ssl.bitly.com/v4/shorten")
        {
            Content = new StringContent($"{{\"long_url\":\"{url}\"}}",
                                            Encoding.UTF8,
                                            "application/json")
        };

        try
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _bitlyToken);

            var response = await client.SendAsync(request).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
                return string.Empty;

            var responsestr = await response.Content.ReadAsStringAsync();

            dynamic jsonResponse = JsonConvert.DeserializeObject<dynamic>(responsestr);
            return jsonResponse["link"];
        }
        catch (Exception ex)
        {
            return string.Empty;
        }
    }

This one is working with V4

TotPeRo
  • 6,561
  • 4
  • 47
  • 60
  • This Should be marked as the correct answer. You can use the nuget as well https://github.com/doublej42/BitlyAPI – RamyRahman May 14 '20 at 10:49
0

This one uses bit.ly API v4:

using System.Collections.Generic;
using RestSharp;
using Newtonsoft.Json.Linq;

private static string API_KEY = Environment.GetEnvironmentVariable("BITLY_ACCESS_TOKEN");
private static string API_URL = "https://api-ssl.bit.ly/v4";

private static string Shorten(string longUrl)
{
    var client = new RestClient(API_URL);
    var request = new RestRequest("shorten");
    request.AddHeader("Authorization", $"Bearer {API_KEY}");
    var param = new Dictionary<string, string> {
        { "long_url", longUrl }
    };
    request.AddJsonBody(param);
    var response = client.Post(request);
    string content = response.Content;
    // WriteLine(content);
    JObject d = JObject.Parse(content);
    var result = (string)d["id"];
    return result;
}

Required 3rd-party packages: Newtonsoft.Json, RestSharp. I also made a GitHub project of it, see here: https://github.com/jabbalaci/CsUrlShortener .

Jabba
  • 19,598
  • 6
  • 52
  • 45
0

This example use only Microsoft .net native code. You not need any other 3rd-party packages like Newtonsoft.Json or RestSharp:

using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using Bitly.Core.Requests;
using Bitly.Core.Responses;

namespace Bitly.Core
{
    public class BitlyClient: IDisposable
    {
        private const string ApiUrl = "https://api-ssl.bitly.com/v4/shorten";
        readonly string _token;
        readonly HttpClient _client;

        public BitlyClient(string token)
        {
            _token = token;
            _client = new HttpClient();
        }

        public async Task<BitlyBaseResponse> ShortenAsync(string urlToShorten)
        {
            var jsonString = JsonSerializer.Serialize(new BitlyRequest{ LongUrl = urlToShorten });

            var request = new HttpRequestMessage(HttpMethod.Post, ApiUrl)
            {
                Content = new StringContent(
                    jsonString,
                    Encoding.UTF8,
                    "application/json"
                    )
            };

            try
            {
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);

                var response = await _client.SendAsync(request).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                    return new BitlyGeneralErrorResponse(response.StatusCode.ToString());
                var stringResponse = await response.Content.ReadAsStringAsync();

                if (stringResponse.Contains("errors"))
                {
                    var jsonErrorResponse = JsonSerializer.Deserialize<BitlyErrorResponse>(stringResponse);
                    return jsonErrorResponse;
                }
                var jsonResponse = JsonSerializer.Deserialize<BitlySuccessResponse>(stringResponse);
                return jsonResponse;
            }
            catch (Exception ex)
            {
                return new BitlyGeneralErrorResponse(ex.Message);
            }
        }

        public void Dispose()
        {
            _client?.Dispose();
        }
    }
}

Request model:

public class BitlyRequest
{
    [JsonPropertyName("long_url")]
    public string LongUrl { get; set; }
}

Response models:

public abstract class BitlyBaseResponse
{
    public abstract bool Success { get; }
    public abstract string Message { get; }
}

public class BitlyErrorResponse : BitlyBaseResponse
{
    public string message { get; set; }
    public string resource { get; set; }
    public string description { get; set; }
    public BitlyResponseError[] errors { get; set; }

    public override bool Success => false;
    public override string Message => message;
}

public class BitlyResponseError
{
    public string field { get; set; }
    public string error_code { get; set; }
}

public class BitlyGeneralErrorResponse : BitlyBaseResponse
{
    public BitlyGeneralErrorResponse(string message)
    {
        Message = message;
    }

    public override bool Success => false;
    public override string Message { get; }
}

public class BitlySuccessResponse : BitlyBaseResponse
{
    public string created_at { get; set; }
    public string id { get; set; }
    public string link { get; set; }
    public object[] custom_bitlinks { get; set; }
    public string long_url { get; set; }
    public bool archived { get; set; }
    public object[] tags { get; set; }
    public object[] deeplinks { get; set; }
    public BitlyResponseReferences references { get; set; }

    public override bool Success => true;
    public override string Message => link;
}

public class BitlyResponseReferences
{
    public string group { get; set; }
}

You can use it like this:

var token = "<your_token>";
var client = new BitlyClient(token);
var url = "https://totpe.ro";
var response = await client.ShortenAsync(url);

You can find all the sample code here

TotPeRo
  • 6,561
  • 4
  • 47
  • 60