How to store Elmah exception information to a web service? - elmah.mvc

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.

Related

Asp.net-core api response WaitingForActivision

Can someone point me into the right direction what I am doing wrong in this Api call? I am getting an odd error that I don’t know what it means. The api call should work as I tested it using VBA and I get a response with the payload. Also any feedback is welcomed.
Id = 190, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}" - this is the response I am getting back from it
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Xml.Linq;
namespace BarcodeScanner.Classes
{
public class Api : IDisposable
{
private readonly TimeSpan _timeout;
private HttpClient _httpClient;
private HttpClientHandler _httpClientHandler;
private readonly string _baseUrl;
private readonly string _credentials;
private const string MediaTypeXml = "application/xml";
public Api(string baseUrl, string authToken, TimeSpan? timeout = null)
{
_baseUrl = NormaliseBaseUrl(baseUrl);
_credentials = Base64Encode(authToken);
_timeout = timeout ?? TimeSpan.FromSeconds(90);
}
public async Task<string> GetAsync(string url)
{
EnsureHttpClientCreated();
using (var response = await _httpClient.GetAsync(url).ConfigureAwait(continueOnCapturedContext: false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
public void Dispose()
{
_httpClientHandler?.Dispose();
_httpClient?.Dispose();
}
private void CreateHttpClient()
{
_httpClientHandler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
};
_httpClient = new HttpClient(_httpClientHandler, false)
{
Timeout = _timeout
};
if (!string.IsNullOrWhiteSpace(_baseUrl))
{
_httpClient.BaseAddress = new Uri(_baseUrl);
}
_httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + _credentials);
}
private void EnsureHttpClientCreated()
{
if (_httpClient == null)
{
CreateHttpClient();
}
}
//call the api
try
{
using (var client = new Api(requestUrl, authToken))
{
var response = client.GetAsync(requestUrl);
}
}
catch (Exception err)
{
throw new Exception("Something went wrong: ", err);
}

GraphQL is returning extra information which is slowing down the initial loading

I am getting some extra information within my graphql results.
Apart from the data and the end errors I am getting
document
operation
perf
extensions
so the result is getting quite bulky. The other think I've noticed is that the initial loading of the documents and the intellisens are taking ages to load.
Any idea how I can get rid of this additional data?
Result of the graphQL query:
GraphQL Controller
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace ElectronConnectQuery.Controllers.v1
{
[Route("[controller]")]
public class GraphQLController : Controller
{
private readonly IDocumentExecuter _documentExecuter;
private readonly ISchema _schema;
private readonly DataLoaderDocumentListener _listener;
private readonly ILogger<GraphQLController> _logger;
public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger)
{
_schema = schema;
_documentExecuter = documentExecuter;
_listener = listener;
_logger = logger;
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
{
if (query == null) { throw new ArgumentNullException(nameof(query)); }
_logger.LogDebug("GraphQL received query:{Query}", query.Query);
var inputs = query.Variables.ToInputs();
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = query.Query,
Inputs = inputs,
ValidationRules = validationRules,
EnableMetrics = false
};
#if (DEBUG)
executionOptions.EnableMetrics = true;
#endif
executionOptions.Listeners.Add(_listener);
var result = await _documentExecuter.ExecuteAsync(executionOptions).ConfigureAwait(false);
if (result.Errors?.Count > 0)
{
return BadRequest(result);
}
return Ok(result);
}
}
}
Instead if writing the result yourself, use the IDocumentWriter, which will properly serialize the result.
/// <summary>
/// Serializes an object hierarchy to a stream. Typically this would be serializing an instance of the ExecutionResult class into a JSON stream.
/// </summary>
public interface IDocumentWriter
{
/// <summary>
/// Asynchronously serializes the specified object to the specified stream.
/// </summary>
Task WriteAsync<T>(Stream stream, T value, CancellationToken cancellationToken = default);
}
There is also an extension method to serialize to a string.
public static async Task<string> WriteToStringAsync<T>(this IDocumentWriter writer, T value)
This example shows using middleware vs. a controller but the idea is the same.
https://github.com/graphql-dotnet/examples/blob/529b530d7a6aad878b2757d776282fdc1cdcb595/src/AspNetCoreCustom/Example/GraphQLMiddleware.cs#L75-L81
private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
await _writer.WriteAsync(context.Response.Body, result);
}
You will need to include GraphQL.SystemTextJson or GraphQL.NewtonSoftJson to choose your implementation of IDocumentWriter.
https://www.nuget.org/packages/GraphQL.SystemTextJson
https://www.nuget.org/packages/GraphQL.NewtonsoftJson
The change which I've done to the controller is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.Instrumentation;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace ElectronConnectQuery.Controllers.v1
{
[Route("[controller]")]
public class GraphQLController : Controller
{
private readonly IDocumentExecuter _documentExecuter;
private readonly ISchema _schema;
private readonly DataLoaderDocumentListener _listener;
private readonly ILogger<GraphQLController> _logger;
private readonly IDocumentWriter _writer;
public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger, IDocumentWriter writer)
{
_schema = schema;
_documentExecuter = documentExecuter;
_listener = listener;
_logger = logger;
_writer = writer;
}
[HttpPost]
public async Task Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
{
if (query == null) { throw new ArgumentNullException(nameof(query)); }
_logger.LogDebug("GraphQL received query:{Query}", query.Query);
var inputs = query.Variables.ToInputs();
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = query.Query,
Inputs = inputs,
ValidationRules = validationRules,
EnableMetrics = false,
};
executionOptions.Listeners.Add(_listener);
var result = await _documentExecuter.ExecuteAsync(opts =>
{
opts.Schema = _schema;
opts.Query = query.Query;
opts.Inputs = inputs;
opts.ValidationRules = validationRules;
opts.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
opts.EnableMetrics = true;
}).ConfigureAwait(false);
result.EnrichWithApolloTracing(DateTime.Now);
await _writer.WriteAsync(Response.Body, result);
}
private async Task WriteResponseAsync(HttpResponse response, ExecutionResult result)
{
response.ContentType = "application/json";
response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
await _writer.WriteAsync(response.Body, result);
}
}
}
Startup.cs
In ConfigureServices
I have added the following lines
// kestrel
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
// IIS
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Also I've registered the DocumentWriter
services.AddScoped<IDocumentWriter, GraphQL.NewtonsoftJson.DocumentWriter>();

Validate JWT in Asp.NET MVC Core using ISecureDataFormat<AuthenticationTicket>

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;
}
}
}
}

Windows universal app isolated storage - How to save and retrieve data?

I have this isolated storage helper and I need to use it to save and retrieve data from my universal app.
I don't know where to begin from. Should I maybe make an app and incorporate the helper class into it?
Here is my class:
using System.IO;
//using System.IO.IsolatedStorage;
using System.Runtime.Serialization.Json;
using System.Text;
public static class IsolatedStorageHelper
{
public static T GetObject<T>(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(key))
{
string serializedObject = localSettings.Values[key].ToString();
return Deserialize<T>(serializedObject);
}
return default(T);
}
public static void SaveObject<T>(string key, T objectToSave)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
string serializedObject = Serialize(objectToSave);
localSettings.Values[key] = serializedObject;
}
public static void DeleteObject(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values.Remove(key);
}
private static string Serialize(object objectToSerialize)
{
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
serializer.WriteObject(ms, objectToSerialize);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
return reader.ReadToEnd();
}
}
}
private static T Deserialize<T>(string jsonString)
{
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
}
use static SaveObject method and supply the 'person' entity and a key. Retrieve it later using GetObject.
But I think in this scenario you should use database sqlite and sqlite net package to save the entity.

How to get Twitter Followers in my ASP.NET MVC3 Application?

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.

Resources