In my mvc3 application i have used DotNetOpenAuth to authorize twitter user,it works perfect. (user can click on sign in button-> twitter login page will open -> user can pass userid and password-> and login successful)
Now i want to display all followers list.
my code is as follows::=>
Helper-TwitterConsumer.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.Contracts;
using System.IO;
using System.Net;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using DotNetOpenAuth.ApplicationBlock;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
namespace NerdDinner.Helpers
{
/// <summary>
/// A consumer capable of communicating with Twitter.
/// </summary>
public static class TwitterConsumer {
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with actually reading/writing
/// a user's private Twitter data.
/// </summary>
public static readonly ServiceProviderDescription ServiceDescription = new ServiceProviderDescription {
RequestTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/authorize", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature.
/// </summary>
public static readonly ServiceProviderDescription SignInWithTwitterServiceDescription = new ServiceProviderDescription {
RequestTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/authenticate", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
/// <summary>
/// The URI to get a user's favorites.
/// </summary>
private static readonly MessageReceivingEndpoint GetFavoritesEndpoint = new MessageReceivingEndpoint("http://twitter.com/favorites.xml", HttpDeliveryMethods.GetRequest);
/// <summary>
/// The URI to get the data on the user's home page.
/// </summary>
///
private static readonly MessageReceivingEndpoint GetFollowersEndpoint = new MessageReceivingEndpoint("http://twitter.com/statuses/followers.xml", HttpDeliveryMethods.GetRequest);
private static readonly MessageReceivingEndpoint GetFriendTimelineStatusEndpoint = new MessageReceivingEndpoint("http://twitter.com/statuses/friends_timeline.xml", HttpDeliveryMethods.GetRequest);
private static readonly MessageReceivingEndpoint UpdateProfileBackgroundImageEndpoint = new MessageReceivingEndpoint("http://twitter.com/account/update_profile_background_image.xml", HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
private static readonly MessageReceivingEndpoint UpdateProfileImageEndpoint = new MessageReceivingEndpoint("http://twitter.com/account/update_profile_image.xml", HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
private static readonly MessageReceivingEndpoint VerifyCredentialsEndpoint = new MessageReceivingEndpoint("http://api.twitter.com/1/account/verify_credentials.xml", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
private static InMemoryTokenManager ShortTermUserSessionTokenManager {
get {
var store = HttpContext.Current.Session;
var tokenManager = (InMemoryTokenManager)store["TwitterShortTermUserSessionTokenManager"];
if (tokenManager == null) {
string consumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"];
string consumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"];
if (IsTwitterConsumerConfigured) {
tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret);
store["TwitterShortTermUserSessionTokenManager"] = tokenManager;
} else {
throw new InvalidOperationException("No Twitter OAuth consumer key and secret could be found in web.config AppSettings.");
}
}
return tokenManager;
}
}
private static WebConsumer signInConsumer;
private static object signInConsumerInitLock = new object();
private static WebConsumer TwitterSignIn {
get {
if (signInConsumer == null) {
lock (signInConsumerInitLock) {
if (signInConsumer == null) {
signInConsumer = new WebConsumer(SignInWithTwitterServiceDescription, ShortTermUserSessionTokenManager);
}
}
}
return signInConsumer;
}
}
/// <summary>
/// Initializes static members of the <see cref="TwitterConsumer"/> class.
/// </summary>
static TwitterConsumer() {
// Twitter can't handle the Expect 100 Continue HTTP header.
ServicePointManager.FindServicePoint(GetFavoritesEndpoint.Location).Expect100Continue = false;
}
public static bool IsTwitterConsumerConfigured {
get {
return !string.IsNullOrEmpty(ConfigurationManager.AppSettings["twitterConsumerKey"]) &&
!string.IsNullOrEmpty(ConfigurationManager.AppSettings["twitterConsumerSecret"]);
}
}
public static XDocument GetFollowers(ConsumerBase twitter, string accessToken)
{
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFavoritesEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
public static XDocument GetUpdates(ConsumerBase twitter, string accessToken) {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFriendTimelineStatusEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
public static XDocument GetFavorites(ConsumerBase twitter, string accessToken) {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFavoritesEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
public static XDocument UpdateProfileBackgroundImage(ConsumerBase twitter, string accessToken, string image, bool tile) {
var parts = new[] {
MultipartPostPart.CreateFormFilePart("image", image, "image/" + Path.GetExtension(image).Substring(1).ToLowerInvariant()),
MultipartPostPart.CreateFormPart("tile", tile.ToString().ToLowerInvariant()),
};
HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileBackgroundImageEndpoint, accessToken, parts);
request.ServicePoint.Expect100Continue = false;
IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request);
string responseString = response.GetResponseReader().ReadToEnd();
return XDocument.Parse(responseString);
}
public static XDocument UpdateProfileImage(ConsumerBase twitter, string accessToken, string pathToImage) {
string contentType = "image/" + Path.GetExtension(pathToImage).Substring(1).ToLowerInvariant();
return UpdateProfileImage(twitter, accessToken, File.OpenRead(pathToImage), contentType);
}
public static XDocument UpdateProfileImage(ConsumerBase twitter, string accessToken, Stream image, string contentType) {
var parts = new[] {
MultipartPostPart.CreateFormFilePart("image", "twitterPhoto", contentType, image),
};
HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileImageEndpoint, accessToken, parts);
IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request);
string responseString = response.GetResponseReader().ReadToEnd();
return XDocument.Parse(responseString);
}
public static XDocument VerifyCredentials(ConsumerBase twitter, string accessToken) {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(VerifyCredentialsEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
public static string GetUsername(ConsumerBase twitter, string accessToken) {
XDocument xml = VerifyCredentials(twitter, accessToken);
XPathNavigator nav = xml.CreateNavigator();
return nav.SelectSingleNode("/user/screen_name").Value;
}
/// <summary>
/// Prepares a redirect that will send the user to Twitter to sign in.
/// </summary>
/// <param name="forceNewLogin">if set to <c>true</c> the user will be required to re-enter their Twitter credentials even if already logged in to Twitter.</param>
/// <returns>The redirect message.</returns>
/// <remarks>
/// Call <see cref="OutgoingWebResponse.Send"/> or
/// <c>return StartSignInWithTwitter().<see cref="MessagingUtilities.AsActionResult">AsActionResult()</see></c>
/// to actually perform the redirect.
/// </remarks>
public static OutgoingWebResponse StartSignInWithTwitter(bool forceNewLogin, Uri callback) {
Contract.Requires(callback != null);
var redirectParameters = new Dictionary<string, string>();
if (forceNewLogin) {
redirectParameters["force_login"] = "true";
}
var request = TwitterSignIn.PrepareRequestUserAuthorization(callback, null, redirectParameters);
return TwitterSignIn.Channel.PrepareResponse(request);
}
/// <summary>
/// Checks the incoming web request to see if it carries a Twitter authentication response,
/// and provides the user's Twitter screen name and unique id if available.
/// </summary>
/// <param name="screenName">The user's Twitter screen name.</param>
/// <param name="userId">The user's Twitter unique user ID.</param>
/// <returns>
/// A value indicating whether Twitter authentication was successful;
/// otherwise <c>false</c> to indicate that no Twitter response was present.
/// </returns>
public static bool TryFinishSignInWithTwitter(out string screenName, out int userId) {
screenName = null;
userId = 0;
var response = TwitterSignIn.ProcessUserAuthorization();
if (response == null) {
return false;
}
XDocument xml = VerifyCredentials(TwitterSignIn, response.AccessToken);
XPathNavigator nav = xml.CreateNavigator();
screenName = nav.SelectSingleNode("/user/screen_name").Value;
userId = int.Parse(nav.SelectSingleNode("/user/id").Value);
return true;
}
}
}
Controllers=>AccountController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using FacebookSolution.Models;
using System.Net;
using Newtonsoft.Json.Linq;
using NerdDinner.Helpers;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.ApplicationBlock;
namespace Facebook.Controllers
{
public class AccountController : Controller
{
//
// GET: /Account/LogOn
public ActionResult LogOn()
{
return View();
}
private static InMemoryTokenManager _tokenManager = new InMemoryTokenManager("ksxWgNxWgN8xWgNxWgNWgNg", "H7EfENH7EfEN7H7EfENcr6H4H7EfENNW6AH7EfH7EfENUc");
private InMemoryTokenManager TokenManager
{
get
{
return _tokenManager;
}
}
public ActionResult TwitterOAuth()
{
var twitter = new WebConsumer(TwitterConsumer.ServiceDescription,this.TokenManager);
//Create the URL that we want Twitter to redirect the user to
var oAuthUrl = new Uri(Request.Url.Scheme + "://" + Request.Url.Authority + "/Account/OAuth");
// If we don't yet have access, immediately request it.
twitter.Channel.Send(twitter.PrepareRequestUserAuthorization(oAuthUrl, null, null));
//This shouldn't happen!!
return null;
}
public ActionResult OAuth()
{
var twitter = new WebConsumer(TwitterConsumer.ServiceDescription, this.TokenManager);
// Process the response
var accessTokenResponse = twitter.ProcessUserAuthorization();
// Is Twitter calling back with authorization?
if (accessTokenResponse != null)
{
//Extract the access token & username for use throughout the site
string accessToken = accessTokenResponse.AccessToken;
string username = accessTokenResponse.ExtraData["screen_name"];
CreateAuthCookie(username, accessToken);
}
else
{
//If the request doesn't come with an auth token redirect to the login page
return RedirectToAction("Login");
}
//Authentication successful, redirect to the home page
return RedirectToAction("Index", "Home");
}
private void CreateAuthCookie(string username, string token)
{
//Get ASP.NET to create a forms authentication cookie (based on settings in web.config)~
HttpCookie cookie = FormsAuthentication.GetAuthCookie(username, false);
//Decrypt the cookie
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
//Create a new ticket using the details from the generated cookie, but store the username &
//token passed in from the authentication method
FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(
ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
ticket.IsPersistent, token);
// Encrypt the ticket & store in the cookie
cookie.Value = FormsAuthentication.Encrypt(newticket);
// Update the outgoing cookies collection.
Response.Cookies.Set(cookie);
}
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
In above code i have written
private static readonly MessageReceivingEndpoint GetFollowersEndpoint = new
MessageReceivingEndpoint("http://twitter.com/statuses/followers.xml", HttpDeliveryMethods.GetRequest);
and
public static XDocument GetFollowers(ConsumerBase twitter, string accessToken)
{
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFavoritesEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
Now what can i do to get list of followers in my view.
Related
I am using .Net framework 4.6.1 and Swashbuckle version 5.3.2 in my WebApi project. Swagger UI is not giving an option to send the input as a request body to my POST Api which uses a custom model binder.
- Model Used :
[ModelBinder(typeof(FieldValueModelBinder))]
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string City { get; set; }
}
- API Post method used:
[HttpPost]
// POST: api/Employee
public HttpResponseMessage Post([ModelBinder(typeof(FieldValueModelBinder))]Employee emp)
{
if (!ModelState.IsValid)
return Request.CreateResponse(HttpStatusCode.BadRequest, "Please provide valid input");
else
//Add Employee logic here
return Request.CreateResponse(HttpStatusCode.OK, "Employee added sucessfully");
}
- Model Binder used :
public class FieldValueModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
/// <summary>
/// Store received data in API in KeyValuePair
/// </summary>
private List<KeyValuePair<string, string>> kvps;
/// <summary>
/// Storing error while binding data in Model class
/// </summary>
private Dictionary<string, string> dictionaryErrors = new Dictionary<string, string>();
/// <summary>
/// Implementing Base method and binding received data in API to its respected property in Model class
/// </summary>
/// <param name="actionContext">Http Action Context</param>
/// <param name="bindingContext">Model Binding Context</param>
/// <returns>True if no error while binding. False if any error occurs during model binding</returns>
public bool BindModel(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
{
try
{
var bodyString = actionContext.Request.Content.ReadAsStringAsync().Result;
if (actionContext.Request.Method.Method.ToUpper().Equals("GET"))
{
var uriContext = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
if (uriContext.HasKeys())
{
this.kvps = uriContext.AllKeys.ToDictionary(k => k, k => uriContext[k]).ToList<KeyValuePair<string, string>>();
}
}
else if (!string.IsNullOrEmpty(bodyString))
{
this.kvps = this.ConvertToKvps(bodyString);
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Please provide valid input data.");
return false;
}
}
catch (Exception ex)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Please provide data in a valid format.");
return false;
}
// Initiate primary object
var obj = Activator.CreateInstance(bindingContext.ModelType);
try
{
this.SetPropertyValues(obj);
}
catch (Exception ex)
{
if (this.dictionaryErrors.Any())
{
foreach (KeyValuePair<string, string> keyValuePair in this.dictionaryErrors)
{
bindingContext.ModelState.AddModelError(keyValuePair.Key, keyValuePair.Value);
}
}
else
{
bindingContext.ModelState.AddModelError("Internal Error", ex.Message);
}
this.dictionaryErrors.Clear();
return false;
}
// Assign completed Mapped object to Model
bindingContext.Model = obj;
return true;
}
I am facing below issues:
When we use ‘ModelBinder’ in our post method, Swagger UI is
displaying this screen where the input parameter are posted in a
query string and CustomModelBinder is invoked and tries to read
request body to perform model binding and validation and gets null in
this case.
Public HttpResponseMessage Post([ModelBinder(typeof(FieldValueModelBinder))]Employee emp)
When we use ‘FromBody’ in our post method, Swagger UI displays this
screen where we can send the input in a request body, but in this
case CustomModelBinder is not invoked and we are not able to perform
modelbinding and validation.
public HttpResponseMessage Post([FromBody]Employee emp)
When we try using both ‘modelbinder’ and ‘frombody’, Swagger UI takes
the input as a query and we get the below response:
Tried with Postman, the API works fine and we are able to pass the input in request body and get the proper output. The custom model binding also works and populates the error message in case of invalid model state and we can then use those messages to send in the response.
What needs to be changed to invoke the custom model binder from Swagger UI while posting input data to API in request body. Please Suggest.
You can do that with an IDocumentFilter here is the code:
private class ApplyDocumentVendorExtensions : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry s, IApiExplorer a)
{
if (swaggerDoc != null)
{
foreach (var path in swaggerDoc.paths)
{
if (path.Value.post != null && path.Value.post.parameters != null )
{
var parameters = path.Value.post.parameters;
if (parameters.Count == 3 && parameters[0].name.StartsWith("emp"))
{
path.Value.post.parameters = EmployeeBodyParam;
}
}
}
}
}
private IList<Parameter> EmployeeBodyParam
{
get
{
return new List<Parameter>
{
new Parameter {
name = "emp",
#in = "body",
required = true,
schema = new Schema {
#ref = "#/definitions/Employee"
}
}
};
}
}
}
I used Stormpath - Token Authentication in ASP.NET Core solution to generate JWT with my logic. Now I need to validate the token if the client (moblie app) sends it back to me.
Any idea how?
Thnx
ASP .NET MVC allows you to create your own authentication mechanism as action filter.
For example:
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Filters;
using System.Web.Http.Results;
using WebAPI.SignatureTypes;
namespace WebAPI.ActionFilters
{
/// <summary>
/// Add this attribute to a controller or action to enforce token-based authentication
/// </summary>
public class TokenRequired : Attribute, IAuthenticationFilter
{
#region Static members for configurations and initialization of reusable components
static TokenRequired()
{
TokenValidator = new JwtSecurityTokenHandler();
Trace.Assert(Realm == null, "The realm should be set by the WebApiConfig class.");
Trace.Assert(TokenValidations == null, "The token validation parameters should be initialized by the Use() function.");
}
public static Uri Realm { get; internal set; }
public static TokenValidationParameters TokenValidations { get; internal set; }
// NuGet: Install-Package System.IdentityModel.Tokens.Jwt
public static ISecurityTokenValidator TokenValidator { get; internal set; }
internal static void Use(Type hashType)
{
var map = new Dictionary<Type, TokenValidationParameters>
{
[typeof(HMACSHA256)] = HmacSignatureFactory.ValidationParameters
};
TokenValidationParameters validations = null;
if (!map.TryGetValue(hashType, out validations))
{
throw new NotSupportedException($"Hashing algorithm of type '{hashType}' is not supported.");
}
TokenValidations = validations;
}
#endregion
/// <summary>
/// Only one instance of this attribute can be applied to a single class or function
/// </summary>
public bool AllowMultiple
{
get
{
return false;
}
}
/// <summary>
/// Deny access if a token is missing from the header Authorization, or invalid; otherwise, let the request goes through.
/// </summary>
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
Trace.Assert(TokenValidator != null, "TokenValidator is required for authentication");
Trace.Assert(TokenValidations != null, "TokenValidations are required for authentication");
AuthenticationHeaderValue authentication = null;
SecurityToken securityToken = null;
try
{
authentication = context.Request.Headers.Authorization;
context.Principal = TokenValidator.ValidateToken(authentication.Parameter, TokenValidations, out securityToken);
}
catch (Exception error)
{
Trace.TraceError($"Missing or invalid token. Error: {error}");
}
if (authentication == null || authentication.Scheme != "Bearer" || securityToken == null)
{
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
}
return Task.FromResult(0);
}
/// <summary>
/// Return a challenge response with the realm included in the header WWW-Authenticate
/// </summary>
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
context.Result = new ChallengeResult(context.Result, Realm);
return Task.FromResult(0);
}
/// <summary>
/// The challenge response to unauthenticated requests
/// </summary>
private class ChallengeResult : IHttpActionResult
{
private IHttpActionResult contextResult;
private Uri realm;
public ChallengeResult(IHttpActionResult contextResult, Uri realm)
{
this.contextResult = contextResult;
this.realm = realm;
}
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = await contextResult.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Bearer", $"realm=\"{realm}\""));
return response;
}
}
}
}
We have been using elmah for some time now and we have a new requirement for the ui dont saving information directly to he database and the manager of the team asked if we can tell elmah to send the exception information to a web service. Does anyone have done this and or have any information to share, thanks.
I implemented this hope it helps someone:
The web service:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Mail;
using System.Web.Http;
using System.Xml;
using System.Xml.Linq;
using Elmah;
using Newtonsoft.Json;
namespace ElmahExt.Service.Controllers
{
public class ElmahCommandsController : ApiController
{
private readonly string _connection = ConfigurationManager.ConnectionStrings["conSQL"].ConnectionString ;
[HttpPost]
public HttpResponseMessage LogError(Error elmahErrorInformation)
{
try
{
var id = Guid.NewGuid();
using (SqlConnection cnn = new SqlConnection(_connection))
using (SqlCommand cmd = SqlCommands.LogError(elmahErrorInformation,id.ToString()))
{
cmd.Connection = cnn;
cnn.Open();
cmd.ExecuteNonQuery();
return Request.CreateResponse(HttpStatusCode.OK, id.ToString());
}
}
catch
{
return Request.CreateResponse(HttpStatusCode.ExpectationFailed,string.Empty);
}
}
[HttpGet]
public HttpResponseMessage GetErrors(string appName, int pageIndex, int pageSize)
{
using (SqlConnection cnn = new SqlConnection(_connection))
using (SqlCommand cmd = SqlCommands.GetErrorsXml(appName, pageIndex, pageSize))
{
cmd.Connection = cnn;
cnn.Open();
XmlReader reader = cmd.ExecuteXmlReader();
try
{
int? total =(int?)cmd.Parameters["#TotalCount"].Value ?? 0;
List<string> errors = new List<string>();
while (reader.IsStartElement("error"))
errors.Add(reader.ReadOuterXml());
XDocument doc = new XDocument(
new XElement("GetErrorsResult",
new XAttribute("total", total),
from string error in errors
select new XElement("Error", error)
)
);
return Request.CreateResponse(HttpStatusCode.OK, doc.ToString());
}
finally
{
reader.Close();
}
}
}
[HttpGet]
public HttpResponseMessage GetError(string appName, string id)
{
Guid errorGuid = new Guid(id);
string errorXml;
using (SqlConnection cnn = new SqlConnection(_connection))
using (SqlCommand cmd = SqlCommands.GetErrorXml(appName, errorGuid))
{
cmd.Connection = cnn;
cnn.Open();
errorXml = (string)cmd.ExecuteScalar();
}
XElement errorEl = (errorXml == null) ? null : new XElement("Error", errorXml);
XDocument doc = new XDocument(
new XElement("GetErrorResult", errorEl)
);
return Request.CreateResponse(HttpStatusCode.OK, doc.ToString());
}
}
}
Elmah extension
using System;
using System.Collections;
using System.Linq;
using System.Net.Http;
using System.Net.Mail;
using System.Threading.Tasks;
using System.Xml.Linq;
using Elmah;
namespace ElmahExt
{
public class ServiceErrorLog : ErrorLog
{
private string _url;
public ServiceErrorLog(IDictionary config)
{
\\Here config have the information from the configuration in the web config
ApplicationName = config["applicationName"] as string ?? "";
_url = config["WebServiceUrl"] as string ?? "";
}
static ServiceErrorLog()
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
e.SetObserved();
}
public override string Name => "Custom Elmah provider using web services.";
/// <summary>
/// This method log the error information coming from an Elmah call. The result of the web service is received with the guid id of the error but is not waited or returned.
/// This implementation was on purpose to continue the processing.
/// </summary>
/// <param name="error">Elmah object containing all the information of the exception</param>
/// <returns></returns>
public override string Log(Error error)
{
Task T = Task.Factory.StartNew(() =>
{
using (var client = new HttpClient())
{
var result = client.PostAsJsonAsync(_url, error).Result;
}
});
return string.Empty;
}
/// <summary>
/// Return a list of errors to display in the Elmah viewer.
/// </summary>
/// <param name="pageIndex">The index of the page to display</param>
/// <param name="pageSize">The amount of records to display per page</param>
/// <param name="errorEntryList">The list of errors</param>
/// <returns>A list of errors in XML format.</returns>
public override int GetErrors(int pageIndex, int pageSize, IList errorEntryList)
{
int total = 0;
using (var client = new HttpClient())
{
_url += $"?pageIndex={pageIndex}&pageSize={pageSize}&appName={ApplicationName}";
var response = client.GetAsync(_url).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsAsync<string>().Result;
XDocument doc = XDocument.Parse(result);
XElement root = doc.Element("GetErrorsResult");
if (root != null)
{
var errors = from XElement el in root.Elements("Error")
select new
{
value = el.Value,
element = XElement.Parse(el.Value)
};
foreach (var err in errors)
{
string errorId = err.element.Attribute("errorId").Value;
Error error = ErrorXml.DecodeString(err.value);
errorEntryList.Add(new ErrorLogEntry(this, errorId, error));
}
total = int.Parse(root.Attribute("total").Value);
}
}
}
return total;
}
/// <summary>
/// Returns an specific error
/// </summary>
/// <param name="id">The id of the error.(Guid)</param>
/// <returns>Returns an XML with the error information.</returns>
public override ErrorLogEntry GetError(string id)
{
ErrorLogEntry errorLogEntry = null;
using (var client = new HttpClient())
{
_url += $"?id={id}&appName={ApplicationName}";
var response = client.GetAsync(_url).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsAsync<string>().Result;
XDocument doc = XDocument.Parse(result);
XElement root = doc.Element("GetErrorResult");
XElement errorEl = root?.Element("Error");
if (errorEl != null)
{
Error error = ErrorXml.DecodeString(errorEl.Value);
errorLogEntry = new ErrorLogEntry(this, id, error);
}
}
}
return errorLogEntry;
}
}
}
In your web config to have to add the custom provider:
<errorLog type="ElmahExt.ServiceErrorLog, ElmahExt" applicationName="Elmah Evaluation App"
WebServiceUrl="http://localhost:28382/api/ElmahCommands/LogError" />
Note in this configuration section the variables of the web service url and the name of the application used in the constructor of the custom provider.
I am currently working on a project that requires using the Yammer API. The intent is to bypass using a browser, and use HttpWebRequest to do all authentication. Originally, this was working for me, but now I get a 404 error when I try to call GetResponse().
For my URL, I have tried using
https://www.yammer.com/session?client_id={CLIENT_ID}
as well as
https://www.yammer.com/session
using (var stream = webrequest.GetRequestStream())
{
stream.Write(postdata, 0, postdata.Length);
}
try
{
webresponse = webrequest.GetResponse() as HttpWebResponse;
}
catch (WebException ex)
{
webresponse = ex.Response as HttpWebResponse;
}
Have they changed the URL or am I doing something wrong?
The following is my code snippet for yammer authentication. Steve Pescha's article - http://blogs.technet.com/b/speschka/archive/2013/10/05/using-the-yammer-api-in-a-net-client-application.aspx explains how to perform Programmatic yammer authentication. I have customized it according to my needs.
public class YammerSession
{
#region Variables
/// <summary>
/// The client identifier
/// </summary>
private readonly string clientId = "XXXXXXXX";
/// <summary>
/// client secret
/// </summary>
private readonly string clientSecret = "XXXXXXXX";
/// <summary>
/// Cookie container that stores yammer authentication information
/// </summary>
private CookieContainer cookieContainer = new CookieContainer(2);
/// <summary>
/// The user code sent in response to login request
/// </summary>
private string userCode;
/// <summary>
/// The user email
/// </summary>
private string email;
/// <summary>
/// The user password
/// </summary>
private SecureString password;
#endregion
#region Methods
/// <summary>
/// Gets the supported yammer version
/// </summary>
public static int SupportedVersion
{
get
{
return 1;
}
}
/// <summary>
/// Gets the client id.
/// </summary>
public string ClientId
{
get
{
return this.clientId;
}
}
/// <summary>
/// Gets the authenticity token.
/// </summary>
/// <value>
/// The authenticity token.
/// </value>
public string AuthenticityToken { get; private set; }
/// <summary>
/// Gets the token.
/// </summary>
/// <value>
/// The token.
/// </value>
public string Token { get; private set; }
/// <summary>
/// Connects the specified connection.
/// </summary>
public override void Connect()
{
this.InternalLogin(this.Connection.User, this.Connection.Password);
}
/// <summary>
/// Disconnects this instance.
/// </summary>
public override void Disconnect()
{
// Log out
this.InternalLogout(this.Connection.Address);
}
/// <summary>
/// Creates the web request to a service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The service endpoint.</param>
/// <returns>
/// A new HTTP web request.
/// </returns>
public string GetEndpoint(string serviceEndpoint)
{
// Get the uri
var requestUri = string.Format("{0}/api/v{1}/{2}", this.Connection.Address, SupportedVersion, serviceEndpoint);
// return the result
return requestUri;
}
/// <summary>
/// Connects the specified email.
/// </summary>
/// <param name="email">The email.</param>
/// <param name="password">The password.</param>
private void InternalLogin(string email, SecureString password)
{
this.email = email;
this.password = password;
// Get the user code.
this.GetUserCode();
// Now get the bearer token
this.GetBearerToken(this.userCode);
}
/// <summary>
/// Gets the user code.
/// </summary>
private void GetUserCode()
{
string yammerAuthUrl = string.Format("https://www.yammer.com/dialog/oauth?client_id={0}", this.clientId);
string yammerSessionUrl = string.Format("https://www.yammer.com/session?client_id={0}", this.clientId);
// The authenticity token
string authenticityToken = string.Empty;
// Make a get request to Yammer authentication endpoint and get the response
using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl))
{
// Set the cookies
this.SetCookies(webResponse);
// Look for authenticity token
authenticityToken = this.GetAuthenticityToken(SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8));
}
if (!string.IsNullOrEmpty(authenticityToken))
{
// Construct the post body with user login information
string postBody = string.Format(
"{0}{1}{2}{3}{4}{5}{6}",
"utf8=%E2%9C%93&authenticity_token=",
HttpUtility.UrlEncode(authenticityToken),
"&network_permalink=&login=",
HttpUtility.UrlEncode(this.email),
"&password=",
HttpUtility.UrlEncode(this.password.ConvertToUnsecureString()),
"&remember_me=off");
// Make the first post for User Code
HttpWebResponse sessionPostWebResponse = this.MakePostRequestToEndPoint(postBody, yammerSessionUrl);
string postResults = this.GetResponseAsString(sessionPostWebResponse);
// Get the next auth token that was returned. This will be used for logout purposes
this.AuthenticityToken = this.GetAuthenticityToken(postResults);
using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl, true))
{
// Now look for the query string and set the user code
this.userCode = webResponse.ResponseUri.Query;
// Check whether we are in Authorization Page
if (this.userCode.IndexOf("?client_id") >= 0)
{
// Construct the yammer network name
string yammerNetworkName = webResponse.ResponseUri.AbsolutePath.Substring(0, webResponse.ResponseUri.AbsolutePath.ToLower().IndexOf("dialog/"));
// Construct the yammer decision url
string yammerUserAuthDecisionUrl = string.Format(
"{0}{1}{2}{3}{4}",
"https://www.yammer.com",
yammerNetworkName,
"oauth2/decision?client_id=",
this.clientId,
"&redirect_uri=https%3A%2F%2Fwww.yammer.com&response_type=code");
// Construct the Payload for authorization page
string payLoad = "utf8=%E2%9C%93&authenticity_token=" + HttpUtility.UrlEncode(this.AuthenticityToken) + "&allow=Allow";
// Authorize the app by posting the request
using (HttpWebResponse decisionPostWebResponse = this.MakePostRequestToEndPoint(payLoad, yammerUserAuthDecisionUrl))
{
// Reset the user Code
this.userCode = decisionPostWebResponse.ResponseUri.Query;
}
}
// App should have been granted access at this point if it did not already have access.
// Now check whether the code is present in the query string
if (this.userCode.IndexOf("?code=") < 0)
{
throw new ArgumentException(Properties.ErrorMessges.UnableToLogin);
}
this.userCode = this.userCode.Replace("?code=", string.Empty);
}
}
}
/// <summary>
/// Get Yammer Authenticity Token
/// </summary>
/// <param name="rawHtml">The Yammer response that was got after posting to yammer endpoint</param>
/// <returns>The Yammer authenticity token</returns>
private string GetAuthenticityToken(string rawHtml)
{
string result = string.Empty;
int at = rawHtml.IndexOf("<meta name=\"authenticity_token\" id=\"authenticity_token\"");
if (at > -1)
{
// Get the authenticity token string
int et = rawHtml.IndexOf("/>", at + 1);
string tokenText = rawHtml.Substring(at, et - at);
// Get the token value
int ts = tokenText.IndexOf("content=");
int es = tokenText.LastIndexOf("\"");
result = tokenText.Substring(ts + 9, es - ts - 9);
}
return result;
}
/// <summary>
/// Perform a get request to an endpoint and return the Http response
/// </summary>
/// <param name="endPoint">The endpoint to make the request</param>
/// <param name="addCookies">Should cookies be added to the request</param>
/// <returns>The Http Web Response</returns>
private HttpWebResponse MakeGetRequestToEndPoint(string endPoint, bool addCookies = false)
{
HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);
webRequest.Method = "GET";
if (addCookies)
{
webRequest.CookieContainer = this.cookieContainer;
}
return (HttpWebResponse)webRequest.GetResponse();
}
/// <summary>
/// Read the cookies from the web response object and store it in the cookie container instance variable
/// </summary>
/// <param name="webResponse">The Web Response object</param>
private void SetCookies(HttpWebResponse webResponse)
{
const string YAMTRAK_COOKIE = "yamtrak_id";
const string SESSION_COOKIE = "_workfeed_session_id";
const string LOGIN_CSRF_TOKEN_COOKIE = "login_csrf_token";
string cookies = webResponse.Headers["Set-Cookie"];
if (string.IsNullOrEmpty(cookies))
{
this.cookieContainer = new CookieContainer();
}
else
{
// Split the cookie based on , and ;
string[] sepChar = new string[2];
sepChar[0] = ",";
sepChar[1] = ";";
string[] cookieArray = cookies.Split(sepChar, StringSplitOptions.None);
// Declare variables to hold the different types of cookies
string login_csrf_token = string.Empty;
string yammerTrakToken = string.Empty;
string sessionToken = string.Empty;
// Parse the cookie array and store the cookies in the array
for (int i = 0; i < cookieArray.Length; i++)
{
if (cookieArray[i].IndexOf(YAMTRAK_COOKIE) >= 0)
{
yammerTrakToken = cookieArray[i];
}
if (cookieArray[i].IndexOf(SESSION_COOKIE) >= 0)
{
sessionToken = cookieArray[i];
}
if (cookieArray[i].IndexOf(LOGIN_CSRF_TOKEN_COOKIE) >= 0)
{
login_csrf_token = cookieArray[i];
}
}
// Create the cookie container
this.cookieContainer = new CookieContainer();
// Get the value for each of the cookie and add it to the cookie container
if (!string.IsNullOrWhiteSpace(yammerTrakToken))
{
yammerTrakToken = yammerTrakToken.Substring(YAMTRAK_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(YAMTRAK_COOKIE, yammerTrakToken, "/", "www.yammer.com"));
}
if (!string.IsNullOrWhiteSpace(sessionToken))
{
sessionToken = sessionToken.Substring(SESSION_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(SESSION_COOKIE, sessionToken, "/", "www.yammer.com"));
}
if (!string.IsNullOrWhiteSpace(login_csrf_token))
{
login_csrf_token = login_csrf_token.Substring(LOGIN_CSRF_TOKEN_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(LOGIN_CSRF_TOKEN_COOKIE, login_csrf_token, "/", "www.yammer.com"));
}
}
}
/// <summary>
/// Make a post request to an endpoint and return the result
/// </summary>
/// <param name="postBody">The post request payload</param>
/// <param name="endPoint">The endpoint</param>
/// <returns>The response got from the server</returns>
private HttpWebResponse MakePostRequestToEndPoint(string postBody, string endPoint)
{
string responseString = string.Empty;
HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);
webRequest.Method = "POST";
webRequest.CookieContainer = this.cookieContainer;
webRequest.ContentType = "application/x-www-form-urlencoded";
SessionHelper.WritePayLoadToWebRequest(webRequest, postBody);
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
return webResponse;
}
/// <summary>
/// Get Response as string
/// </summary>
/// <param name="webResponse">The http web response object</param>
/// <returns>The web response string</returns>
/// <remarks>The Http Response object would be disposed after use</remarks>
private string GetResponseAsString(HttpWebResponse webResponse)
{
string responseString = string.Empty;
using (webResponse)
{
responseString = SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8);
}
return responseString;
}
/// <summary>
/// Gets the user code.
/// </summary>
/// <param name="userCode">The user code.</param>
/// <exception cref="System.TimeoutException">Waiting for login page load.
/// or
/// Waiting for post login page load.</exception>
private void GetBearerToken(string userCode)
{
string formatUri = string.Format("https://www.yammer.com/oauth2/access_token.json?client_id={0}&client_secret={1}&code={2}", this.clientId, this.clientSecret, userCode);
Uri yammerUri = new Uri(formatUri);
WebRequest webRequest = WebRequest.Create(yammerUri);
webRequest.Method = "GET";
using (WebResponse response = webRequest.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
DataContractJsonSerializer seralizer = new DataContractJsonSerializer(typeof(Model.JSON.Yammer.AccessTokenResponse));
Model.JSON.Yammer.AccessTokenResponse accessTokenResponse = (Model.JSON.Yammer.AccessTokenResponse)seralizer.ReadObject(responseStream);
if (string.IsNullOrWhiteSpace(accessTokenResponse.access_token.token))
{
throw new InvalidOperationException("Unable to extract Yammer.com authorization bearer token.");
}
// Set the bearer token
this.Token = accessTokenResponse.access_token.token;
}
}
}
/// <summary>
/// Internal logout.
/// </summary>
/// <param name="address">The address.</param>
private void InternalLogout(string address)
{
string formatUri = string.Format("{0}/logout?from=nav", address);
Uri yammerUri = new Uri(formatUri);
// Create request
var request = HttpWebRequest.CreateHttp(yammerUri);
// POST
request.Method = "POST";
// Set the cookie container
request.CookieContainer = this.cookieContainer;
// Sent the request body
request.ContentType = "application/x-www-form-urlencoded";
string requestBody = string.Format(
"authenticity_token={0}&_method=delete",
HttpUtility.UrlEncode(this.AuthenticityToken));
byte[] requestBodyUTF8 = Encoding.UTF8.GetBytes(requestBody);
// Set the length before writing the request steam.
request.ContentLength = requestBody.Length;
// Write the request stream
using (var requestStream = request.GetRequestStream())
{
using (StreamWriter streamWrite = new StreamWriter(requestStream))
{
streamWrite.Write(requestBody);
}
}
// Make the request
using (var response = request.GetResponse())
{
// Always read the response
using (Stream responseStream = response.GetResponseStream())
{
}
}
}
#endregion
}
In the above code replace your client Id, client secret, email and password. Then you can use the connect method to get the bearer token and disconnect to log out of yammer.
Recently yammer changed the number of cookies that were passed back and forth and I have fixed the issue
I am trying to hit HTTPS server from Windows Phone Device/Windows Phone Emulator. But the request is not reaching server.
The server has SSL certificate installed and on Windows Phone I manually installed the certificate. But then also not able to proceed.
The request is HTTPS. When we make HTTP request the phone is hitting server and response is coming but for HTTPS it is failing in between.
Please let me know the solution for this.
Thanks in advance.
Below is the lass iam usig for Making a HTTP Web Request:-
public class ConnectionHandler
{
///
/// Holds the status of the connection.
///
public static bool done = false;
/// <summary>
/// Holds the status of the connection
/// Backkey press handling OTRS Ticket#1000543 [25 Jun 13]
/// </summary>
public static bool initiated = false;
/// <summary>
/// Holds the response xml from the server
/// </summary>
public static string strResponseXML
{
get;
set;
}
/// <summary>
/// Holds the parameters related to the request
/// </summary>
public static string strRequestParams
{
get;
set;
}
/// <summary>
/// Holds the server url
/// </summary>
public static string strUrl
{
get;
set;
}
/// <summary>
/// Holds the session cookie
/// </summary>
public static string cookie
{
get;
set;
}
/// <summary>
/// Holds the page name parameter
/// </summary>
public static string pageName
{
get;
set;
}
/// <summary>
/// The method <code>connectToServer</code> sends the asynchronous request to the server.
/// </summary>
public static void connectToServer()
{
// Create the web request object
done = false;
initiated = true;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(strUrl);
PageRequestHandler.CurrentPageURL = strUrl + "?" + strRequestParams;
System.Diagnostics.Debug.WriteLine(System.DateTime.Now + ">>>fullpageRequest>>>" + PageRequestHandler.CurrentPageURL);
System.Diagnostics.Debug.WriteLine(System.DateTime.Now + ">>>PostData>>>" + getParam());
System.Diagnostics.Debug.WriteLine(System.DateTime.Now + ">>>PostData>>>" + strRequestParams);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
//webRequest.Headers["Cookie"] = cookie;
// Start the request
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
while (!done)
{
Thread.Sleep(100);
}
}
/// <summary>
/// The method <code>GetRequestStreamCallback</code> sends the parameters to the request and start getting the response asynchronously.
/// </summary>
/// <param name="asynchronousResult"></param>
static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
//End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Add the request parameters to the web request
//strRequestParams = "Channel=WP7&screenWidth=480&screenHeight=700&page=CheckBoxHome";
byte[] byteArray = Encoding.UTF8.GetBytes(getParam());
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
/// <summary>
/// The method <code>GetResponseCallback</code> receives the response asynchronously and store the response xml in strResponseXML.
/// </summary>
/// <param name="asynchronousResult"></param>
static void GetResponseCallback(IAsyncResult asynchronousResult)
{
StreamReader streamReader = null;
try
{
strResponseXML = "";
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
//cookie=response.Cookies["Set-Cookie"].ToString();
Stream streamResponse = response.GetResponseStream();
streamReader = new StreamReader(streamResponse);
strResponseXML = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
System.Diagnostics.Debug.WriteLine(System.DateTime.Now + ">>>Response xml from server>>>\n" + strResponseXML);
}
catch (WebException e)
{
// Error treatment
// ...
string ex = e.Message;
}
done = true;
initiated = false;
//Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
//{
// strResponseXML = streamReader.ReadToEnd();
//}));
//streamReader.Close();
}
static string GetEncodedValue(string value)
{
if (Convert.ToBoolean(ConfigManager.URL_ENCODE))
{
return HttpUtility.UrlEncode(value);
}
else
return value;
}
static string getParam()
{
string param = "";
if (ConnectionHandler.strRequestParams.Contains("&"))
{
string[] paramArray = strRequestParams.Split('&');
foreach (string keyValue in paramArray)
{
if (keyValue.Contains("="))
{
string[] keys = keyValue.Split('=');
param = param+keys[0]+"="+GetEncodedValue(keys[1])+"&";
}
}
}
else
param = ConnectionHandler.strRequestParams;
return param;
}
}
From HTTP Web Server I downloded the certificate and insalled on phone s well manually.
Pease help i resolving the issue.
Thanks