I am trying to write a plugin to create a new contact entity in Microsoft CRM 2011. I'm yet to find any useful information online and I feel like I've been banging my head against a brick wall all day. The code I have posted below is giving me an error saying "The name 'service' does not exist in the current context". Can anyone tell me what's going on, please?
// <copyright file="PreValidateContactCreate.cs" company="">
// Copyright (c) 2013 All Rights Reserved
// </copyright>
// <author></author>
// <date>8/6/2013 4:22:10 PM</date>
// <summary>Implements the PreValidateContactCreate Plugin.</summary>
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.1
// </auto-generated>
namespace Plugins1
{
using System;
using System.ServiceModel;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Discovery;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;
/// <summary>
/// PreValidateContactCreate Plugin.
/// </summary>
public class PreValidateContactCreate: Plugin
{
/// <summary>
/// Initializes a new instance of the <see cref="PreValidateContactCreate"/> class.
/// </summary>
public PreValidateContactCreate()
: base(typeof(PreValidateContactCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(10, "Create", "contact", new Action<LocalPluginContext>(ExecutePreValidateContactCreate)));
// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}
/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePreValidateContactCreate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
// TODO: Implement your custom Plug-in business logic.
Entity Contact = new Entity("contact");
Contact.Attributes["firstname"] = "SomeName";
Contact.Attributes["lastname"] = "SomeSurname";
service.Create(Contact);
}
}
}
An error is being thrown because service is not yet defined. It needs to be defined before you can call service.Create.
The following is some code that I use for plugins that you might find useful. Seems a bit simpler than your example.
EDIT: I have modified the code to show a Create and an Update
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
namespace PluginSample
{
public class ContactSample : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Get the context
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
try
{
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
if (context.MessageName == "Create")
{
// Creates a contact
Entity contact = new Entity("contact");
contact.Attributes.Add("firstname", "SomeName");
contact.Attributes.Add("lastname", "SomeSurname");
service.Create(contact);
}
else if (context.MessageName == "Update")
{
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// Update contact
Entity contact = new Entity("contact");
contact.Id = new Guid("EBFB262C-5EFF-E211-8BEB-1CC1DEEAE7EC");
contact.Attributes.Add("firstname", "Name Changed");
service.Update(contact);
}
}
}
catch (Exception generalException)
{
throw new InvalidPluginExecutionException("Plugin Failed - Execute :-(", generalException);
}
}
}
}
Use the localContext parameter to get to the org service.
*<param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>*
public class CreateRecord : IPlugin
{
/// <summary>
/// Execute Method
/// </summary>
/// <param name="serviceProvider">IServiceProvider object.</param>
public void Execute(IServiceProvider serviceProvider)
{
//Obtain the tracing service.
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
if (tracingService == null)
throw new Exception("Unable to obtain tracing service.");
//Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context == null)
throw new Exception("Unable to obtain Plugin Execution context.");
//Obtain the organization service reference
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
if (serviceFactory == null)
throw new Exception("Unable to obtain Organization service factory.");
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
if (service == null)
throw new Exception("Unable to obtain organization service.");
Entity contact = new Entity("contact");
contact["firstname"] = "Your First Name";
contact["lastname"] = "Your Last Name";
Guid contactId = service.Create(contact);
}
}
Above code is a sample for creating a record, in this case contact in CRM. contactid should be holding the record which got created.You can locate the created record with other contacts under active contact view.
Hope this helps. Let me know if you need any more help on this. Happy learning !!! :)
Related
Following is the code I am using:
namespace MySite.Api
{
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Net.Http.Headers;
using Microsoft.Extensions.Logging;
/// <summary>
/// API query execution helper
/// </summary>
public class ApiQuery : IApiQuery
{
/// <summary>
/// configuration reference
/// </summary>
private IConfiguration config;
private HmacAuthenticationUtils hmacUtils;
private readonly ILogger logger;
private static readonly HttpClient httpClient = new HttpClient();
private static readonly HttpClient httpClientHMAC = new HttpClient();
/// <summary>
/// Initializes a new instance of the <see cref="ApiQuery"/> class.
/// </summary>
/// <param name="inConfig">injected configuration</param>
public ApiQuery(IConfiguration inConfig, HmacAuthenticationUtils hmacUtils, ILoggerFactory loggerFactory)
{
this.config = inConfig;
this.hmacUtils = hmacUtils;
this.logger = loggerFactory.CreateLogger("perfLogger");
}
/// <summary>
/// HTTP verb post
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <returns>HTTP response message</returns>
public virtual async Task<string> Post(string requestUrl, object requestData, HttpClient client = null)
{
return await PostBypassCache(requestUrl, requestData, client);
}
/// <summary>
/// HTTP verb post, specifically to bypass cache
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <returns>HTTP response message</returns>
public async Task<string> PostBypassCache(string requestUrl, object requestData, HttpClient client = null)
{
DateTime perfStart = DateTime.Now;
string customerJson = string.Empty;
if (requestData is string)
{
customerJson = requestData.ToString();
}
else
{
customerJson = JsonConvert.SerializeObject(requestData);
}
////just some template output to test which I'm getting back.
string resultJson = "{ 'status':'No Content'}";
if (client == null)
{
client = httpClient;
}
var response = await httpClient.PostAsync(requestUrl, new StringContent(customerJson, Encoding.UTF8, "application/json"));
if (response.StatusCode == HttpStatusCode.OK)
{
resultJson = await response.Content.ReadAsStringAsync();
}
logger.LogInformation("response time: " + (DateTime.Now - perfStart).TotalMilliseconds + "ms. Resource:" + requestUrl);
return resultJson;
}
/// <summary>
/// HTTP verb post
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <param name="headerset">header data</param>
/// <returns>string data</returns>
public async Task<string> PostHmacAuth(string requestUrl, string requestData)
{
var httpRequest = new HttpRequestMessage(HttpMethod.Post, requestUrl);
httpRequest.Content = new StringContent(requestData, Encoding.UTF8, "application/json");
var signature = await Utils.GenerateAuthenticationString(httpRequest);
httpClientHMAC.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(HmacAuthenticationUtils.HmacHeader, signature);
return await PostBypassCache(requestUrl, requestData, httpClientHMAC);
}
}
}
In the Startup.cs, I inject it
services.AddTransient<IApiQuery, ApiQuery>();
I have recently made these changes as previously the code was actually instantiating the httpClient in each of the method, i.e.,
var client = new HttpClient();
At some places it was like:
using(var client = new HttpClient()){}
I Think due to such code, the the appPool is showing error due to which my IIS hangs, and the problem only get solved by restarting the appPool. I conclude this to be problem as I went through a lot of other articles. What I was not able to conclude is on if it should be a good idea to inject the ApiQuery Service as singleton itself.
Will it be better to inject it as ?
As I am injecting IApiQuery to every business service right now as a transient service, will it be good idea ? Any thoughts
HttpClient should be singleton-scoped. There's a finite number of connections available on your machine, and since HttpClient holds on to connections it creates, having multiple instances floating around can quickly exhaust your connection pool.
Beginning with ASP.NET Core 2.1, there exists IHttpClientFactory which provides a simple and reusable way of injecting properly scoped HttpClient instances. However, since you're using 1.1, that's not available to you. The recommended path would be to upgrade your project to 2.1. The 1.X line of ASP.NET Core is frankly trash. It wasn't ready for production use, despite being an official release.
If you insist on sticking with 1.1, then you'll need to implement your own method of reusing HttpClient instances. The most straightforward way is to use "accessor" classes, which you can then utilize to inject different HttpClients into different objects. For example:
public class ApiHttpClientAccessor : IDisposable
{
public ApiHttpClientAccessor()
{
HttpClient = new HttpClient
{
BaseAddress = new Uri("https://foo.com")
};
}
public HttpClient HttpClient { get; }
private bool _disposed;
public virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
HttpClient.Dispose();
}
_disposed = true;
}
public bool Dispose() =>
Dispose(true);
}
Then, you can register this accessor class as a singleton, meaning it will only be created once (so the contained HttpClient will also only be created once). Then, set up your class to accept this accessor in its constructor:
public class ApiQuery : IApiQuery
{
private readonly HttpClient _client;
public ApiQuery(ApiHttpClientAccessor httpClientAccessor)
{
_client = (httpClientAccessor ?? throw new ArgumentNullException(nameof(httpClientAccessor))).HttpClient;
}
...
}
And in Startup.cs:
services.AddSingleton<ApiHttpClientAccessor>();
services.AddTransient<IApiQuery, ApiQuery>();
I did use this documentation:
https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html
to implement Interface Interceptors. To handle my async calls I used the IAsyncInterceptor interface described here:
https://github.com/JSkimming/Castle.Core.AsyncInterceptor
The registration code I came up with does look like this:
builder.Register(c => new CallResultLoggerInterceptor())
.Named<IAsyncInterceptor>("log-calls");
builder.RegisterType<AppointmentService>()
.As<IAppointmentService>()
.EnableInterfaceInterceptors()
.InstancePerDependency();
where the AppointmentService has an InterceptAttribute.
[Intercept("log-calls")]
public class AppointmentService : IAppointmentService
...
When i call the containers Build() method, it throws an ComponentNotRegisteredException with the message:
The requested service 'log-calls (Castle.DynamicProxy.IInterceptor)' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
which is correct because I do not implement IInterceptor but IAsyncInterceptor. I guess the problem is the concrete implementation of EnableInterfaceInterceptors in autofac using the "wrong" extension method of the ProxyGenerator - but how can I solve this?
Cheers,
Manuel
You need to register a named IInterceptor for Autofac interceptors to work. You're registering an IAsyncInterceptor. That won't work.
Note Autofac has no support for this extended async interceptor extension you're using. If you want to get that to work, it'll require writing a custom adapter of some nature to get it to respond to IInterceptor.
You can see my answer in the issue of Castle.Core.AsyncInterceptor:
https://github.com/JSkimming/Castle.Core.AsyncInterceptor/issues/42#issuecomment-592074447
create an adapter
public class AsyncInterceptorAdaper<TAsyncInterceptor> : AsyncDeterminationInterceptor
where TAsyncInterceptor : IAsyncInterceptor
{
public AsyncInterceptorAdaper(TAsyncInterceptor asyncInterceptor)
: base(asyncInterceptor)
{ }
}
create your async interceptor
public class CallLoggerAsyncInterceptor : AsyncInterceptorBase
{
....
}
relate the interceptor to interface
[Intercept(typeof(AsyncInterceptorAdaper<CallLoggerAsyncInterceptor>))]
public interface ISomeType
register to IoC container
//register adapter
builder.RegisterGeneric(typeof(AsyncInterceptorAdaper<>));
//register async interceptor
builder.Register(c => new CallLoggerAsyncInterceptor(Console.Out));
I've made a code sample in https://github.com/wswind/aop-learn/blob/master/AutofacAsyncInterceptor
I've created my own extension method for registering application services.
This extension method simply prepares input parameter for castle core ProxyGenerator.
using System;
using System.Collections.Generic;
using System.Linq;
using Castle.DynamicProxy;
using Autofac;
namespace pixi.Extensions
{
public static class AutofacExtensions
{
private static readonly ProxyGenerator _proxyGenerator = new ProxyGenerator();
/// <summary>
/// Use this extension method to register default interceptors <code>UnitOfWorkInterceptor</code>
/// and <code>LoggingInterceptor</code> on your application service implementations. If you need custom
/// interceptors that are not part of infrastructure but are part of specific business module then pass
/// in those interceptors in params explicitly.
/// </summary>
/// <param name="builder"></param>
/// <param name="interceptors"></param>
/// <typeparam name="TImplementation"></typeparam>
/// <typeparam name="TService"></typeparam>
/// <exception cref="ArgumentException"></exception>
public static void RegisterApplicationService<TImplementation, TService>(this ContainerBuilder builder, params Type[] interceptors)
where TImplementation : class
{
ValidateInput<TService>(interceptors);
builder.RegisterType<TImplementation>().AsSelf();
builder.Register(c =>
{
var service = c.Resolve<TImplementation>();
var resolvedInterceptors = ResolveInterceptors<TImplementation, TService>(interceptors, c);
return (TService) _proxyGenerator.CreateInterfaceProxyWithTarget(
typeof(TService),
service,
ProxyGenerationOptions.Default,
resolvedInterceptors
);
}).As<TService>();
}
private static void ValidateInput<TService>(Type[] interceptors)
{
if (!typeof(TService).IsInterface)
throw new ArgumentException("Type must be interface");
if (interceptors.Any(i => i != typeof(IAsyncInterceptor)))
throw new ArgumentException("Only IAsyncInterceptor types are expected");
}
private static IAsyncInterceptor[] ResolveInterceptors<TImplementation, TService>(Type[] interceptors,
IComponentContext c) where TImplementation : class
{
var resolvedInterceptors = new List<IAsyncInterceptor>
{
c.Resolve<LoggingInterceptor>(),
c.Resolve<UnitOfWorkInterceptor>()
}.Concat(interceptors
.Where(i => i != typeof(UnitOfWorkInterceptor)
&& i != typeof(LoggingInterceptor))
.Select(i => (IAsyncInterceptor) c.Resolve(i))).ToArray();
return resolvedInterceptors;
}
}
}
I am using castle core for unit of work and logging hence the name UnitOfWorkInterceptor and LogginInterceptor. Change these two to your desired defaults. Default interceptors must be registered in this way:
public class SomeModule: Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<UnitOfWorkInterceptor>().AsSelf();
builder.RegisterType<LoggingInterceptor>().AsSelf();
builder.RegisterApplicationService<SampleService, ISampleService>();
builder.RegisterType<SampleRepository>().As<ISampleRepository>();
}
}
In the above code snippet I've also demonstrated the usage provided extension method. Doing it this way I get red of tag interfaces and placing extra attributes on interfaces. That way I can keep my ApplicationService interfaces free of framework/3rd party library dependencies.
I hope this helps.
Well, I am a new guy who is trying to develop a web application whose user are will be authenticated through Facebook. I am developing the application in MVC 4 .Net Framework. As it's internal programs are already done so I need not to do much coding. I have just put the API ID and Secret Key in the scope
OAuthWebSecurity.RegisterFacebookClient(
appId: "750397051803327",
appSecret: "**************************");
And here is my Application http://imgur.com/a/k4Vd0
My Application is taking properly the user permission from the user perfectly. http://imgur.com/a/bqzj5 but after taking permission it is not providing the login state of the user by showing such exception http://imgur.com/a/h81Oh login failed. I debugged form the code end and I observed that it is sending isLoggedin as false http://imgur.com/a/UuLIe therefore my I am not getting the access.
However 2 days before I am not getting such exception. I was getting data simply fine. Here is a snapshot of my previous data. http://imgur.com/a/Bc49F
I need that data again, but how? Is there anything need to change in my application dashboard? Possibly I have changed something in application dashboard. if yes then what is particularly that?
Another things I'm confused that what is the need for PRODUCTS? Do I need anything from the products for this special reason to get the data. If yes then which one shall I need and how to configure it to get back my previous systematic process in which I was getting data smoothly.
If I add App Center from the PRODUCTS I am obtaining two other secret keys like Account Kit App Secret and Account Kit Client Token Is that I need to use these keys for my requested case. For such login approval specific which Products are need or nothing need at all from PRODUCTS. I am so confused about it how to configure an application.
Please suggest me how to solve this problem in addition how to configure my application API. Thank you.
According to Previous Answer I got my solution. In MVC4 everyone write down their AppID and SecurityCode. Due to change of facebook GRAPH API those previous links are broken. Consequently everyone need to change the RegisterFacebookClient calss. But this class is a sealed class in the .Net library, so anyone can't extend or overwrite it. As a result we need to use a wrapper class. Let us consider my Wrapper class is FacebookClientV2Dot3 therefore my class will be
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using DotNetOpenAuth.AspNet.Clients;
using Newtonsoft.Json;
public class FacebookClientV2Dot3 : OAuth2Client
{
#region Constants and Fields
/// <summary>
/// The authorization endpoint.
/// </summary>
private const string AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth";
/// <summary>
/// The token endpoint.
/// </summary>
private const string TokenEndpoint = "https://graph.facebook.com/oauth/access_token";
/// <summary>
/// The user info endpoint.
/// </summary>
private const string UserInfoEndpoint = "https://graph.facebook.com/me";
/// <summary>
/// The app id.
/// </summary>
private readonly string _appId;
/// <summary>
/// The app secret.
/// </summary>
private readonly string _appSecret;
/// <summary>
/// The requested scopes.
/// </summary>
private readonly string[] _requestedScopes;
#endregion
/// <summary>
/// Creates a new Facebook OAuth2 client, requesting the default "email" scope.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
public FacebookClient(string appId, string appSecret)
: this(appId, appSecret, new[] { "email" }) { }
/// <summary>
/// Creates a new Facebook OAuth2 client.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
/// <param name="requestedScopes">One or more requested scopes, passed without the base URI.</param>
public FacebookClient(string appId, string appSecret, params string[] requestedScopes)
: base("facebook")
{
if (string.IsNullOrWhiteSpace(appId))
throw new ArgumentNullException("appId");
if (string.IsNullOrWhiteSpace(appSecret))
throw new ArgumentNullException("appSecret");
if (requestedScopes == null)
throw new ArgumentNullException("requestedScopes");
if (requestedScopes.Length == 0)
throw new ArgumentException("One or more scopes must be requested.", "requestedScopes");
_appId = appId;
_appSecret = appSecret;
_requestedScopes = requestedScopes;
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
var state = string.IsNullOrEmpty(returnUrl.Query) ? string.Empty : returnUrl.Query.Substring(1);
return BuildUri(AuthorizationEndpoint, new NameValueCollection
{
{ "client_id", _appId },
{ "scope", string.Join(" ", _requestedScopes) },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
{ "state", state },
});
}
protected override IDictionary<string, string> GetUserData(string accessToken)
{
var uri = BuildUri(UserInfoEndpoint, new NameValueCollection { { "access_token", accessToken } });
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
using (var webResponse = webRequest.GetResponse())
using (var stream = webResponse.GetResponseStream())
{
if (stream == null)
return null;
using (var textReader = new StreamReader(stream))
{
var json = textReader.ReadToEnd();
var extraData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToString());
data.Add("picture", string.Format("https://graph.facebook.com/{0}/picture", data["id"]));
return data;
}
}
}
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
var uri = BuildUri(TokenEndpoint, new NameValueCollection
{
{ "code", authorizationCode },
{ "client_id", _appId },
{ "client_secret", _appSecret },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
});
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
string accessToken = null;
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
// handle response from FB
// this will not be a url with params like the first request to get the 'code'
Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);
using (StreamReader sr = new StreamReader(response.GetResponseStream(), rEncoding))
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
var jConvert = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(jsonObject));
Dictionary<string, object> desirializedJsonObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jConvert.ToString());
accessToken = desirializedJsonObject["access_token"].ToString();
}
return accessToken;
}
private static Uri BuildUri(string baseUri, NameValueCollection queryParameters)
{
var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k]));
var qs = String.Join("&", keyValuePairs);
var builder = new UriBuilder(baseUri) { Query = qs };
return builder.Uri;
}
/// <summary>
/// Facebook works best when return data be packed into a "state" parameter.
/// This should be called before verifying the request, so that the url is rewritten to support this.
/// </summary>
public static void RewriteRequest()
{
var ctx = HttpContext.Current;
var stateString = HttpUtility.UrlDecode(ctx.Request.QueryString["state"]);
if (stateString == null || !stateString.Contains("__provider__=facebook"))
return;
var q = HttpUtility.ParseQueryString(stateString);
q.Add(ctx.Request.QueryString);
q.Remove("state");
ctx.RewritePath(ctx.Request.Path + "?" + q);
}
}
Look here you I have replaces all the API links by newer version links.
Now you need to modify your
AuthConfig
Just use a wrapper class
OAuthWebSecurity.RegisterClient(new FacebookClientV2Dot3("AppID", "HassedPassword"));
Then all success. You facebook login will be back in previous state.
However you can face a new issue regarding this new API rather than previous API, the problem is that IP Whitelisting. Like this image. Hope you will need nothing but this. Happy coding.
Yes!!!!
I got the solution of my own problem. According to Facebook developers bug report all Facebook log is not working from 28th March 2017. They also let us know through their developers Facebook group. The post link is here.
According to one of the Developer teams had said we're finding that
facebook authentication just stopped working (2pm EST) across multiple
apps that we manage. apps haven't changed, apps haven't been
suspended..... not sure where to report this since "status" is all
good......
What am I missing?
I'm trying to read with NOLOCK using a TransactionScope like this:
var scopeOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted };
using (var scope = new TransactionScope(TransactionScopeOption.Required, scopeOptions))
{
using (var db = new MyDbContext(ConnectionStringEntities))
{
// Simple read with a try catch block...
}
scope.Complete();
}
I expected to see with NOLOCK added to the SQL query (looking in SQL Profiler and also a custom DbCommandInterceptor - but it's not there...
UPDATE: after some more research, I wonder if the selected cursor is being used after all, just without the NOLOCK "hint" (SQL Server specific - and also specific to just one table), I found some code that get the current transaction and it seem to show the right selected transaction isolation (ReadUncommitted / Serializable etc.)I still want to test it but let me know if you have any thoughts
Get current .net TransactionScope IsolationLevel
Transaction trans = Transaction.Current;
System.Transactions.IsolationLevel level = trans.IsolationLevel;
LogService.Instance.Debug($"Transaction IsolationLevel = {level.ToString()}");
So it looks like Entity Framework does respect the IsolationLevel, only it does not use the NOLOCK hint (probably because it is too database specific) and this by the way my main complaint against EF - that it is not very optimized for different database types, another example is where the new identity is saving a GUID primary key for AspNetUsers as a string (again for lack of optimization) other than that (and few other things) EF is awesome!
I could not find a solution to my problem anywhere, I definitely didn't want to make all my queries use NOLOCK - just the uncommitted ones, so I ended up combining two solutions (with some changes):
NoLockInterceptor - for adding NOLOCK on the fly (Entity Framework with NOLOCK):
/// <summary>
/// Add "WITH (NOLOCK)" hint to SQL queries, SQL Server specifc - may break queries on different databases.
/// (conditionally turn off with NoLockInterceptor.AddNoLockHintToSqlQueries = false to change on runtime)
/// <para>
/// https://stackoverflow.com/questions/926656/entity-framework-with-nolock
/// </para>
/// </summary>
public class NoLockInterceptor : DbCommandInterceptor
{
private static readonly Regex TableAliasRegex = new Regex(
#"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))",
RegexOptions.Multiline | RegexOptions.IgnoreCase);
/// <summary>
/// Add "WITH (NOLOCK)" hint to SQL queries - unique to each thread
/// (set to true only when needed and then back to false)
/// </summary>
[ThreadStatic]
public static bool AddNoLockHintToSqlQueries;
public NoLockInterceptor()
{
// Do not use by default for all queries
AddNoLockHintToSqlQueries = false;
}
public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
if (AddNoLockHintToSqlQueries)
{
command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
if (AddNoLockHintToSqlQueries)
{
command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
}
TransactionWrapper - to invoke the NoLockInterceptor behaviour and also useful for repeated use of transactions (http://haacked.com/archive/2009/08/18/simpler-transactions.aspx/):
/// <summary>
/// Transaction wrapper for setting pre-defined transaction scopes
/// <para>
/// http://haacked.com/archive/2009/08/18/simpler-transactions.aspx/
/// </para>
/// </summary>
public static class TransactionWrapper
{
/// <summary>
/// Set transaction scope and using NoLockInterceptor for adding SQL Server specific "WITH (NOLOCK)"
/// to ReadUncommitted isolation level transactions (not supported by Entity Framework)
/// </summary>
/// <param name="isolationLevel"></param>
/// <param name="transactionScopeOption"></param>
/// <param name="timeout"></param>
/// <param name="action"></param>
public static void SetScope(IsolationLevel isolationLevel, TransactionScopeOption transactionScopeOption,
TimeSpan timeout, Action action)
{
var transactionOptions = new TransactionOptions { IsolationLevel = isolationLevel, Timeout = timeout };
using (var transactionScope = new TransactionScope(transactionScopeOption, transactionOptions))
{
if (isolationLevel == IsolationLevel.ReadUncommitted)
NoLockInterceptor.AddNoLockHintToSqlQueries = true;
action();
transactionScope.Complete();
if (isolationLevel == IsolationLevel.ReadUncommitted)
NoLockInterceptor.AddNoLockHintToSqlQueries = false;
}
}
}
Use it like this:
var timeout = TimeSpan.FromSeconds(ConfigVariables.Instance.Timeout_Transaction_Default_In_Seconds);
TransactionWrapper.SetScope(IsolationLevel.ReadUncommitted, TransactionScopeOption.Required, timeout, () =>
{
using (var db = new MyDbContext(MyDbContextConnectionStringEntities))
{
// Do stuff...
}
});
NOLOCK is now added just to queries with a ReadUncommitted transaction isolation level scopes.
You can't get Entity Framework to render the NOLOCK hint. If you want to read un-committed data, you have to do something different like what you did by adding the TransactionScope with IsolationLevel.ReadUncommited to the TransactionOptions.
Writing your own command interceptor or your own EF provider would also work.
https://msdn.microsoft.com/en-us/data/dn469464.aspx
I've tried transaction scope and it then profile the calls to the DB. EF begins and ends the transaction but never changes the isolation level from Read Committed.
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions()
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
List<T> toReturn = query.ToList();
scope.Complete();
return toReturn;
}
I have all the Nuget Bits for SignalR , I am trying to use my own clientIDs as well as the dependency Injection container that comes with SignalR for all my other repositories and such. Now the strange thing is this jQuery to connect to the hub fails on:
debugger;
// Proxy created on the fly
var chat = $.connection.chat;
Basically, the chat object becomes undefined as if SignalR cannot be resolved. This started happening once I tried to overide the default resolver for SignalR with the code below.
What am I missing here?
Another issue I am having is I am not sure if my UserClientIDfactory which implements IConnectionIdFactory
is working either.
Here is the MVC3 code in my Global.asax
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<UserIdClientIdFactory>()
.To<UserIdClientIdFactory>()
.InRequestScope();
//Rest of the other stuff to inject
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//ninject calls to create the kernal etc
IKernel kernel = CreateKernel();
//TO DO using signal IR resolver
var resolver = new NinjectDependencyResolver(kernel);
SignalR.Hosting.AspNet.AspNetHost.SetResolver(resolver);
}
Finally, here is the code for my custom clientIDfactory
public class UserIdClientIdFactory : IConnectionIdFactory
{
#region IConnectionIdFactory Members
string IConnectionIdFactory.CreateConnectionId(SignalR.Hosting.IRequest request)
{
// get and return the UserId here, in my app it is stored
// in a custom IIdentity object, but you get the idea
return HttpContext.Current.User.Identity.Name != null ?
//TO DO change to get profileID from Appfabric or the database and log user infor
HttpContext.Current.User.Identity.Name.ToString() :
Guid.NewGuid().ToString();
}
#endregion
}
As I read your question you ask how to do proper dependency injection in ASP.NET MVC and SignalR using the same DI container (and hence only need to declare bindings in one place). If this is correct understood, I once wrote a blog post regarding this: http://lcdev.dk/2012/02/14/using-signalr-ninject-with-asp-net-mvc3-and-the-ninject-mvc3-nuget-package/
In the blog post I assume that you are using ASP.NET MVC3 as well as the Ninject.MVC3 and the SignalR.Ninject Nuget packages.
However, if this is not the case I do have a comment to your code. To me it seems like that the kernel used to make your bindings (in RegisterServices) is not the kernel you actually register with SignalR. And if this is the case, then of course SignalR won't know about your intended bindings and might throw an exception as result of your use of an un-instantiated object reference -> which then might explain why you no longer can connect to your SignalR hub.
ok thanks for the your post man, made me do some more digging , I read the rest of the post you linked about how to use Ninject with MVC3 which lead me to realize that I had ninject but not the Nuget Bits for Ninject Mvc3 , I added that and alos modifed my global.asax using the following post
http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/
here is the working code in gloabal.asax I also removed the bootstrapper that NinJect mvc3 added to the application start folder since that is how it works in the above post
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.IgnoreRoute("{*allaxd}", new { allaxd = #".*\.axd(/.*)?" }); //added for mango chat
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
public override void Init()
{
this.AuthenticateRequest += new EventHandler(MvcApplication_AuthenticateRequest);
this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
base.Init();
}
#region "Ninject stuff for dependancy Injection
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
// kernel.Load(Assembly.GetExecutingAssembly());
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<UserIdClientIdFactory>()
.To<UserIdClientIdFactory>()
.InRequestScope();
SignalR.Hosting.AspNet.AspNetHost.DependencyResolver.Register(typeof(IConnectionIdFactory), () => new UserIdClientIdFactory());
}
#endregion
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
//for project awesome
ModelMetadataProviders.Current = new AwesomeModelMetadataProvider();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}