/// <summary> /// Retrieve the company's updates /// </summary> public Companies.CompanyUpdates GetShares( UserAuthorization user , int id , FieldSelector<Companies.CompanyUpdates> fields = null ) { const string urlFormat = "/v1/companies/{int id}/updates"; var url = FormatUrl(urlFormat, fields, "int id", id); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.CompanyUpdates>(context); return result; }
/// <summary> /// /// </summary> public Companies.CompanySearch Search( UserAuthorization user , int start , int count , string keywords , FieldSelector<Companies.CompanySearch> fields = null ) { const string urlFormat = "/v1/company-search{FieldSelector}?start={int start}&count={int count}&keywords={keywords}"; var url = FormatUrl(urlFormat, fields, "int start", start, "int count", count, "keywords", keywords); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.CompanySearch>(context); return result; }
internal T HandleXmlResponse <T>(RequestContext context) where T : class, new() { T result = null; ApiError errorResult = null; // create serializers // it may fail if attributes are wrong XmlSerializer serializer, errorSerializer; try { serializer = new XmlSerializer(typeof(T)); errorSerializer = new XmlSerializer(typeof(ApiError)); } catch (Exception ex) { throw FX.InternalException("SerializerCtor", ex, ex.Message); } if (validHttpCodes.Contains(context.HttpStatusCode)) { // the HTTP code matches a success response try { result = (T)serializer.Deserialize(context.ResponseStream); } catch (Exception ex) { var ex1 = FX.InternalException("SerializerDeserialize", ex, ex.Message); TryAttachContextDetails(context, ex1); throw ex1; } } else if (errorHttpCodes.Contains(context.HttpStatusCode)) { // the HTTP code matches a error response try { errorResult = (ApiError)serializer.Deserialize(context.ResponseStream); } catch (Exception ex) { var ex1 = FX.InternalException("SerializerDeserializeError", ex, ex.Message); TryAttachContextDetails(context, ex1); throw ex1; } { var ex1 = FX.ApiException("ApiErrorResult", errorResult.Status, errorResult.Message, context.UrlPath); TryAttachContextDetails(context, null); ex1.Data.Add("ErrorResult", errorResult); if (errorResult != null) { if (errorResult.Status == 401) { ex1.Data["ShouldRenewToken"] = true; } } throw ex1; } } else { // unknown HTTP code var ex1 = FX.ApiException("ApiUnknownHttpCode", context.HttpStatusCode); TryAttachContextDetails(context, null); throw ex1; } if (result == null) { var ex1 = FX.ApiException("ApiEmptyResult"); TryAttachContextDetails(context, null); throw ex1; } return(result); }
/// <summary> /// This returns an array of companies that match to the specified email domain. /// </summary> public Companies.Company GetListByEmailDomain( UserAuthorization user , string universalName , FieldSelector<Companies.Company> fields = null ) { const string urlFormat = "/v1/companies/universal-name={UniversalName}{FieldSelector}"; var url = FormatUrl(urlFormat, fields, "UniversalName", universalName); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.Company>(context); return result; }
/// <summary> /// the public profile of a user /// </summary> /// <remarks> /// See https://developer.linkedin.com/documents/profile-api /// </remarks> public Profiles.Person GetPublicProfile( UserAuthorization user , string publicProfileUrl , string[] acceptLanguages , FieldSelector<Profiles.Person> fields = null ) { const string urlFormat = "/v1/people/url={PublicProfileUrl}{FieldSelector}"; var url = FormatUrl(urlFormat, fields, "PublicProfileUrl", publicProfileUrl); var context = new RequestContext(); context.UserAuthorization = user; context.AcceptLanguages = acceptLanguages; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Person>(context); return result; }
/// <summary> /// retrieve the member's updates /// </summary> public Social.UserUpdates GetMyUpdates( UserAuthorization user , int start = 0 , int count = 50 , DateTime? before = null , DateTime? after = null , bool showHiddenMembers = false , FieldSelector<Social.UserUpdates> fields = null ) { const string urlFormat = "/v1/people/~/network/updates?scope=self&start={int start = 0}&count={int count = 50}&before={DateTime? before = null}&after={DateTime? after = null}&show-hidden-members={bool showHiddenMembers = false}"; var url = FormatUrl(urlFormat, fields, "int start = 0", start, "int count = 50", count, "DateTime? before = null", before, "DateTime? after = null", after, "bool showHiddenMembers = false", showHiddenMembers); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Social.UserUpdates>(context); return result; }
/// <summary> /// Hacker Summary /// </summary> public async Task<Companies.Company> GetListAsync( UserAuthorization user , FieldSelector<Companies.Company> fields = null ) { const string urlFormat = "/v1/companies{FieldSelector}"; var url = FormatUrl(urlFormat, fields); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.Company>(context); return result; }
/// <summary> /// returns the original picture posted by the user, fields selector are ignored /// </summary> public Profiles.PictureUrls GetOriginalProfilePicture( UserAuthorization user ) { var url = "/v1/people/~/picture-urls::(original)"; var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.PictureUrls>(context); return result; }
/// <summary> /// returns the original picture posted by the user, fields selector are ignored /// </summary> public async Task<Profiles.PictureUrls> GetProfilePictureAsync( UserAuthorization user , short width , short height ) { const string urlFormat = "/v1/people/~/picture-urls::({short width}x{short height})"; var url = FormatUrl(urlFormat, default(FieldSelector), "short width", width, "short height", height); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.PictureUrls>(context); return result; }
/// <summary> /// returns the original picture posted by the user, fields selector are ignored /// </summary> public async Task<Profiles.PictureUrls> GetOriginalProfilePictureAsync( UserAuthorization user , string memberToken ) { const string urlFormat = "/v1/people/id={MemberToken}/picture-urls::(original)"; var url = FormatUrl(urlFormat, default(FieldSelector), "MemberToken", memberToken); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.PictureUrls>(context); return result; }
/// <summary> /// returns a list of 1st degree connections for a user /// </summary> public async Task<Profiles.Connections> GetUpdatedConnectionsByProfileIdAsync( UserAuthorization user , string memberToken , int start , int count , long modifiedSince , FieldSelector<Profiles.Connections> fields = null ) { const string urlFormat = "/v1/people/id={MemberToken}/connections{FieldSelector}?start={int start}&count={int count}&modified=updated&modified-since={long modifiedSince}"; var url = FormatUrl(urlFormat, fields, "MemberToken", memberToken, "int start", start, "int count", count, "long modifiedSince", modifiedSince); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Connections>(context); return result; }
/// <summary> /// returns a list of 1st degree connections for a user /// </summary> public async Task<Profiles.Connections> GetConnectionsByPublicProfileAsync( UserAuthorization user , string publicProfileUrl , int start , int count , FieldSelector<Profiles.Connections> fields = null ) { const string urlFormat = "/v1/people/url={PublicProfileUrl}/connections{FieldSelector}?start={int start}&count={int count}"; var url = FormatUrl(urlFormat, fields, "PublicProfileUrl", publicProfileUrl, "int start", start, "int count", count); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Connections>(context); return result; }
/// <summary> /// the profile of a user in the network /// </summary> /// <remarks> /// See https://developer.linkedin.com/documents/profile-api /// </remarks> public async Task<Profiles.Person> GetProfileByIdAsync( UserAuthorization user , string memberToken , string[] acceptLanguages , FieldSelector<Profiles.Person> fields = null ) { const string urlFormat = "/v1/people/id={MemberToken}{FieldSelector}"; var url = FormatUrl(urlFormat, fields, "MemberToken", memberToken); var context = new RequestContext(); context.UserAuthorization = user; context.AcceptLanguages = acceptLanguages; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Person>(context); return result; }
/// <summary> /// Share a new company update. /// </summary> /// <remarks> /// See https://developer.linkedin.com/creating-company-shares /// </remarks> public Common.PostShareResult Share( UserAuthorization user , int companyId , Common.PostShare postData ) { const string urlFormat = "/v1/companies/{int companyId}/shares"; var url = FormatUrl(urlFormat, default(FieldSelector), "int companyId", companyId); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "POST"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; this.CreateJsonPostStream(context, postData); if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Common.PostShareResult>(context); result.Location = this.ReadHeader<string>(context, "Location"); return result; }
/// <summary> /// Retrieve the company's updates /// </summary> public async Task<Companies.CompanyUpdates> GetSharesAsync( UserAuthorization user , int id , int start , int count , string type , FieldSelector<Companies.CompanyUpdates> fields = null ) { const string urlFormat = "/v1/companies/{int id}/updates?start={int start}&count={int count}&event-type={type}"; var url = FormatUrl(urlFormat, fields, "int id", id, "int start", start, "int count", count, "type", type); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; var exec = await this.ExecuteQueryAsync(context); if (!exec) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.CompanyUpdates>(context); return result; }
/// <summary> /// returns a list of 1st degree connections for a user /// </summary> public Profiles.Connections GetMyConnections( UserAuthorization user , int start , int count , FieldSelector<Profiles.Connections> fields = null ) { const string urlFormat = "/v1/people/~/connections{FieldSelector}?start={int start}&count={int count}"; var url = FormatUrl(urlFormat, fields, "int start", start, "int count", count); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Connections>(context); return result; }
private static async Task BufferizeResponseAsync(RequestContext context, Stream readStream) { if (context.BufferizeResponseStream) { var memory = new MemoryStream(); context.ResponseStream = memory; byte[] buffer = new byte[1024 * 1024]; int readBytes = 0; while ((readBytes = await readStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await memory.WriteAsync(buffer, 0, readBytes); } memory.Seek(0L, SeekOrigin.Begin); } else { context.ResponseStream = readStream; } }
/// <summary> /// returns the original picture posted by the user, fields selector are ignored /// </summary> public Profiles.PictureUrls GetProfilePicture( UserAuthorization user , string memberToken , short width , short height ) { const string urlFormat = "/v1/people/id={MemberToken}/picture-urls::({short width}x{short height})"; var url = FormatUrl(urlFormat, default(FieldSelector), "MemberToken", memberToken, "short width", width, "short height", height); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.PictureUrls>(context); return result; }
internal async Task<bool> ExecuteQueryAsync(RequestContext context) { // https://developer.linkedin.com/documents/request-and-response-headers if (context == null) throw new ArgumentNullException("context"); if (string.IsNullOrEmpty(context.Method)) throw new ArgumentException("The value cannot be empty", "context.Method"); if (string.IsNullOrEmpty(context.UrlPath)) throw new ArgumentException("The value cannot be empty", "context.UrlPath"); var request = (HttpWebRequest)HttpWebRequest.Create(context.UrlPath); request.Method = context.Method; request.UserAgent = LibraryInfo.UserAgent; request.Headers.Add("x-li-format", "json"); if (context.AcceptLanguages != null) { request.Headers.Add(HttpRequestHeader.AcceptLanguage, string.Join(",", context.AcceptLanguages)); } // user authorization if (context.UserAuthorization != null) { if (string.IsNullOrEmpty(context.UserAuthorization.AccessToken)) throw new ArgumentException("The value cannot be empty", "context.UserAuthorization.AccessToken"); request.Headers.Add("Authorization", "Bearer " + context.UserAuthorization.AccessToken); } foreach (var header in context.RequestHeaders) { request.Headers[header.Key] = header.Value; } // post stuff? if (context.PostData != null) { try { if (context.PostDataType != null) request.ContentType = context.PostDataType; ////request.ContentLength = context.PostData.Length; var stream = await request.GetRequestStreamAsync(); await stream.WriteAsync(context.PostData, 0, context.PostData.Length); await stream.FlushAsync(); } catch (WebException ex) { throw new InvalidOperationException("Error POSTing to API (" + ex.Message + ")", ex); } catch (Exception ex) { throw new InvalidOperationException("Error POSTing to API (" + ex.Message + ")", ex); } } // get response HttpWebResponse response; WebException webException = null; try { response = (HttpWebResponse)await request.GetResponseAsync(); context.HttpStatusCode = (int)response.StatusCode; context.ResponseHeaders = response.Headers; var readStream = response.GetResponseStream(); await BufferizeResponseAsync(context, readStream); // check HTTP code if (!(response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)) { throw new InvalidOperationException("Error from API (HTTP " + (int)(response.StatusCode) + ")"); } return true; } catch (WebException ex) { webException = ex; } if (webException != null) { response = (HttpWebResponse)webException.Response; if (response != null) { context.HttpStatusCode = (int)response.StatusCode; context.ResponseHeaders = response.Headers; var stream = response.GetResponseStream(); if (stream != null) { await BufferizeResponseAsync(context, stream); var responseString = await new StreamReader(context.ResponseStream, Encoding.UTF8).ReadToEndAsync(); context.ResponseStream.Seek(0L, SeekOrigin.Begin); return false; } throw new InvalidOperationException("Error from API (HTTP " + (int)(response.StatusCode) + "): " + webException.Message, webException); } else { throw new InvalidOperationException("Error from API: " + webException.Message, webException); } } else { return true; } }
/// <summary> /// returns a list of 1st degree connections for a user /// </summary> public Profiles.Connections GetUpdatedConnectionsByPublicProfile( UserAuthorization user , string publicProfileUrl , int start , int count , long modifiedSince , FieldSelector<Profiles.Connections> fields = null ) { const string urlFormat = "/v1/people/url={PublicProfileUrl}/connections{FieldSelector}?start={int start}&count={int count}&modified=updated&modified-since={long modifiedSince}"; var url = FormatUrl(urlFormat, fields, "PublicProfileUrl", publicProfileUrl, "int start", start, "int count", count, "long modifiedSince", modifiedSince); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Profiles.Connections>(context); return result; }
/// <summary> /// retrieve a company by using the company ID /// </summary> public Companies.Company GetById( UserAuthorization user , string companyId , FieldSelector<Companies.Company> fields = null ) { const string urlFormat = "/v1/companies/{CompanyId}{FieldSelector}"; var url = FormatUrl(urlFormat, fields, "CompanyId", companyId); var context = new RequestContext(); context.UserAuthorization = user; context.Method = "GET"; context.UrlPath = this.LinkedInApi.Configuration.BaseApiUrl + url; if (!this.ExecuteQuery(context)) this.HandleJsonErrorResponse(context); var result = this.HandleJsonResponse<Companies.Company>(context); return result; }
/// <summary> /// Gets the access token for a authorization code. /// </summary> /// <param name="authorizationCode">The authorization code.</param> /// <param name="redirectUri">The redirect URI.</param> /// <returns></returns> /// <exception cref="System.ArgumentException"> /// The value cannot be empty;authorizationCode /// or /// The value cannot be empty;redirectUri /// </exception> /// <exception cref="System.InvalidOperationException"> /// Failed to read API response /// or /// Error from API (HTTP + (int)(response.StatusCode) + ) /// or /// Error from API: + ex.Message /// or /// API responded with an empty response /// </exception> public AuthorizationAccessToken GetAccessToken(string authorizationCode, string redirectUri) { if (string.IsNullOrEmpty(authorizationCode)) throw new ArgumentException("The value cannot be empty", "authorizationCode"); if (string.IsNullOrEmpty(redirectUri)) throw new ArgumentException("The value cannot be empty", "redirectUri"); this.CheckConfiguration(apiSecretKey: true); var url = string.Format( "{0}/uas/oauth2/accessToken?grant_type=authorization_code&code={1}&redirect_uri={2}&client_id={3}&client_secret={4}", this.LinkedInApi.Configuration.BaseOAuthUrl, Uri.EscapeDataString(authorizationCode), Uri.EscapeDataString(redirectUri), Uri.EscapeDataString(this.LinkedInApi.Configuration.ApiKey), Uri.EscapeDataString(this.LinkedInApi.Configuration.ApiSecretKey)); var context = new RequestContext { Method= "POST", UrlPath = url, }; this.ExecuteQuery(context); AuthorizationAccessToken result = null; OAuth2Error errorResult = null; // read response content try { if (context.HttpStatusCode == 200 || context.HttpStatusCode == 201) { #if NET35 var reader = new StreamReader(context.ResponseStream, Encoding.UTF8); var json = reader.ReadToEnd(); result = Newtonsoft.Json.JsonConvert.DeserializeObject<AuthorizationAccessToken>(json); #else var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(AuthorizationAccessToken)); result = (AuthorizationAccessToken)serializer.ReadObject(context.ResponseStream); #endif result.AuthorizationDateUtc = DateTime.UtcNow; } else { #if NET35 var reader = new StreamReader(context.ResponseStream, Encoding.UTF8); var json = reader.ReadToEnd(); errorResult = Newtonsoft.Json.JsonConvert.DeserializeObject<OAuth2Error>(json); #else var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(OAuth2Error)); errorResult = (OAuth2Error)serializer.ReadObject(context.ResponseStream); #endif throw FX.ApiException("OAuth2ErrorResult", errorResult.Error, errorResult.ErrorMessage); } } catch (Exception ex) { throw new InvalidOperationException("Failed to read API response", ex); } if (result == null) { throw new InvalidOperationException("API responded with an empty response"); } return result; }
internal bool ExecuteQuery(RequestContext context) { // https://developer.linkedin.com/documents/request-and-response-headers if (context == null) { throw new ArgumentNullException("context"); } if (string.IsNullOrEmpty(context.Method)) { throw new ArgumentException("The value cannot be empty", "context.Method"); } if (string.IsNullOrEmpty(context.UrlPath)) { throw new ArgumentException("The value cannot be empty", "context.UrlPath"); } var request = (HttpWebRequest)HttpWebRequest.Create(context.UrlPath); request.Method = context.Method; request.UserAgent = LibraryInfo.UserAgent; request.Headers.Add("x-li-format", "json"); if (context.AcceptLanguages != null) { request.Headers.Add(HttpRequestHeader.AcceptLanguage, string.Join(",", context.AcceptLanguages)); } // user authorization if (context.UserAuthorization != null) { if (string.IsNullOrEmpty(context.UserAuthorization.AccessToken)) { throw new ArgumentException("The value cannot be empty", "context.UserAuthorization.AccessToken"); } request.Headers.Add("Authorization", "Bearer " + context.UserAuthorization.AccessToken); } foreach (var header in context.RequestHeaders) { request.Headers[header.Key] = header.Value; } // post stuff? if (context.PostData != null) { try { if (context.PostDataType != null) { request.ContentType = context.PostDataType; } ////request.ContentLength = context.PostData.Length; var stream = request.GetRequestStream(); stream.Write(context.PostData, 0, context.PostData.Length); stream.Flush(); } catch (WebException ex) { throw new InvalidOperationException("Error POSTing to API (" + ex.Message + ")", ex); } catch (Exception ex) { throw new InvalidOperationException("Error POSTing to API (" + ex.Message + ")", ex); } } // get response HttpWebResponse response; try { response = (HttpWebResponse)request.GetResponse(); context.HttpStatusCode = (int)response.StatusCode; context.ResponseHeaders = response.Headers; var readStream = response.GetResponseStream(); BufferizeResponse(context, readStream); // check HTTP code if (!(response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)) { throw new InvalidOperationException("Error from API (HTTP " + (int)(response.StatusCode) + ")"); } return(true); } catch (WebException ex) { response = (HttpWebResponse)ex.Response; if (response != null) { context.HttpStatusCode = (int)response.StatusCode; context.ResponseHeaders = response.Headers; var stream = response.GetResponseStream(); if (stream != null) { BufferizeResponse(context, stream); var responseString = new StreamReader(context.ResponseStream, Encoding.UTF8).ReadToEnd(); context.ResponseStream.Seek(0L, SeekOrigin.Begin); return(false); } throw new InvalidOperationException("Error from API (HTTP " + (int)(response.StatusCode) + "): " + ex.Message, ex); } else { throw new InvalidOperationException("Error from API: " + ex.Message, ex); } } }