Programmatically disposing of the Elmah email onMailing - asp.net

I have an issue with Elmah, I've overriden the Mailing method. And I want it to dispose of the mail (not send it basically) when my App isn't in Live mode. Problem is when I do this, when my ErrorHandler (in my ASP.NET MVC app) tries to raise the exception with Elmah, i get the error: Cannot access a disposed object. Object name:'System.Net.Mail.MailMessage'. So I need to figure out a way around this. Code below:
Emailing method:
public static void ErrorMail_Mailing(object sender, ErrorMailEventArgs e)
{
if (!GlobalHelper.IsLiveMode)
{
//e.Mail.Dispose();
}
else
{
MailAddressCollection MAC = new MailAddressCollection();
foreach (string a in EmailRecipients.Split(','))
{
MAC.Add(a);
}
string b = "errors#" + GlobalHelper.AppName + ".com";
e.Mail.From = new MailAddress(b);
e.Mail.To.Clear(); // Clears existing mail addresses
e.Mail.To.Add(MAC.ToString());
e.Mail.Subject = GlobalHelper.AppName+ " Error: ("+e.Error.Type.Substring(0,10)+") Deployment Level:"+GlobalHelper.DeploymentMode;
}
Errorhandler method:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class CustomHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
// Bail if we can't do anything; app will crash.
if (context == null)
return;
var ex = context.Exception ?? new Exception("No further information exists.");
// Can show Data on view page /w this code
// var data = new ErrorPresentation
//{
// ErrorMessage = HttpUtility.HtmlEncode(ex.Message),
// TheException = ex,
// ShowMessage = !(filterContext.Exception == null),
// ShowLink = false
//};
//filterContext.Result = View("ErrorPage", data);
context.ExceptionHandled = true;
//Log to Elmah
ErrorSignal.FromCurrentContext().Raise(ex);
//Show Custom view page
context.Result = new ViewResult { ViewName = "Error" };
}
}
Stack trace:
System.Net.Mail.SmtpException: Failure sending mail. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Mail.MailMessage'.
at System.Net.Mail.MailMessage.get_AlternateViews()
at System.Net.Mail.MailMessage.SetContent()
at System.Net.Mail.SmtpClient.Send(MailMessage message)
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at Elmah.ErrorMailModule.SendMail(MailMessage mail)
at Elmah.ErrorMailModule.ReportError(Error error)
at Elmah.ErrorMailModule.OnError(Exception e, HttpContext context)
at Elmah.ErrorMailModule.OnErrorSignaled(Object sender, ErrorSignalEventArgs args)
at Elmah.ErrorSignalEventHandler.Invoke(Object sender, ErrorSignalEventArgs args)
at Elmah.ErrorSignal.Raise(Exception e, HttpContext context)
at Elmah.ErrorSignal.Raise(Exception e)
at MusingMonkey.Utilities.Filters.CustomHandleErrorAttribute.OnException(ExceptionContext context) in C:\Users\William-Business\Desktop\TWB\TWB Central\Projects\MusingMonkey\MusingMonkey\Utilities\Filters\ErrorHandler.cs:line 34
at System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList`1 filters, Exception exception)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__3(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<BeginProcessRequest>b__2()
at System.Web.Mvc.SecurityUtil.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust[TResult](Func`1 func)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

The problem is that ELMAH is trying to use the MailMessage in order to send it but you have already disposed the object. The best solution for you would be to not do this via the event, but by inheriting from the ErrorMailModule and overriding it's SendMail method like this:
protected override void SendMail(MailMessage mail)
{
if (!GlobalHelper.IsLiveMode)
base.SendMail(mail);
}
You can then continue to do the rest in your Mailing event handler.

Related

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream'. With HttpClient

I need to send parallel several Post requests. For this I'm going to use the following code:
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"key={customer.FCMServerKey}");
var obj = new
{
to = customer.FcmRegistrationId,
notification = new
{
title = push.PushTitle,
body = push.PushBody,
}
};
string json = JsonConvert.SerializeObject(obj);
var data = new StringContent(json, Encoding.UTF8, "application/json");
responseTasks.Add( client.PostAsync("https://fcm.googleapis.com/fcm/send", data));
pushes.Add(push);
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("\nException with pushing!");
Console.WriteLine("Message :{0} ", ex.Message);
}
}
var responses = await Task.WhenAll(responseTasks);
var count = 0;
foreach (var response in responses)
{
var responseBody = await response.Content.ReadAsStringAsync();
pushes[count].FCMResponse = responseBody;
pushes[count].Sent = response.IsSuccessStatusCode;
Console.WriteLine("FCM response:");
Console.WriteLine(pushes[count].FCMResponse);
count++;
}
await _pushRepository.SaveAsync(pushes);
}
As you can see, I put my task objects into the responseTasks. Then I'm going to send all requests with the help of this line:
var responses = await Task.WhenAll(responseTasks);
I as result I have this exception:
Unhandled Exception: System.Threading.Tasks.TaskCanceledException: The operation was canceled. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 size, CancellationToken cancellationToken)
at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.BeginAuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState)
at System.Net.Security.SslStream.<>c.b__47_0(SslClientAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state)
at System.Threading.Tasks.TaskFactory1.FromAsyncImpl[TArg1,TArg2](Func5 beginMethod, Func2 endFunction, Action1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func5 beginMethod, Action1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func5 beginMethod, Action1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
at System.Net.Security.SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
What is wrong?
please check how using works:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement
In your code client will be disposed as soon as using block ends but you still have pending tasks on responseTasks list that will try to access it. You need to get results while in client using block.

Error Trying to Load DefaultNLP Model in Stanford.NLP.CoreNLP .Net in WebAPI C# Project

I have been attempting to load the default models I pulled from the suggested ZIP file. Generally, I am loading the annotation into a singleton at the application level so the resources can be shared across all sessions. (in WebAPI OWIN Startup, this is being called from startup.cs).
Trying other methods with relative path references, I was getting this error:
unable to resolve
"edu/stanford/nlp/models/pos-tagger/english-left3words/english-left3words-distsim.tagger"
as either class path, filename or URL
I am not sure if I am getting closer to or further from a solution. This is at the root directory of my ASP.NET WebAPI Project:
However, I am getting the error:
Unhandled Execution Error
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: java.lang.reflect.InvocationTargetException:
Source Error:
Line 43: // We should change current directory, so
StanfordCoreNLP could find all the model files automatically Line 44:
Directory.SetCurrentDirectory(HostingEnvironment.MapPath(ModelLocation));
Line 45: pipeline = new StanfordCoreNLP(props); Line
46: } Line 47: finally
Source File: D:\xxx\xxx\xxx\NLP.cs Line: 45
Stack Trace:
[InvocationTargetException] __(Object[] ) +444
FastConstructorAccessorImpl.newInstance(Object[] args) +28
java.lang.reflect.Constructor.newInstance(Object[] initargs, CallerID
) +133 edu.stanford.nlp.util.ClassFactory.createInstance(Object[]
params) +108
[ClassCreationException: MetaClass couldn't create public
edu.stanford.nlp.time.TimeExpressionExtractorImpl(java.lang.String,java.util.Properties)
with args [sutime, {}]]
edu.stanford.nlp.util.ClassFactory.createInstance(Object[] params)
+372 edu.stanford.nlp.util.MetaClass.createInstance(Object[] objects) +34
edu.stanford.nlp.util.ReflectionLoading.loadByReflection(String
className, Object[] arguments) +71
[ReflectionLoadingException: Error creating
edu.stanford.nlp.time.TimeExpressionExtractorImpl]
edu.stanford.nlp.util.ReflectionLoading.loadByReflection(String
className, Object[] arguments) +232
edu.stanford.nlp.time.TimeExpressionExtractorFactory.create(String
className, String name, Properties props) +80
edu.stanford.nlp.time.TimeExpressionExtractorFactory.createExtractor(String
name, Properties props) +34
edu.stanford.nlp.ie.regexp.NumberSequenceClassifier..ctor(Properties
props, Boolean useSUTime, Properties sutimeProps) +57
edu.stanford.nlp.ie.NERClassifierCombiner..ctor(Boolean
applyNumericClassifiers, Boolean useSUTime, Properties nscProps,
String[] loadPaths) +129
edu.stanford.nlp.pipeline.AnnotatorImplementations.ner(Properties
properties) +454 edu.stanford.nlp.pipeline.6.create() +46
edu.stanford.nlp.pipeline.AnnotatorPool.get(String name) +163
edu.stanford.nlp.pipeline.StanfordCoreNLP.construct(Properties ,
Boolean , AnnotatorImplementations ) +555
edu.stanford.nlp.pipeline.StanfordCoreNLP..ctor(Properties props,
Boolean enforceRequirements) +55
edu.stanford.nlp.pipeline.StanfordCoreNLP..ctor(Properties props) +76
XXX.XXX.NLP.Start(String modelLocation) in
D:\xxx\xxx\xxx\NLP.cs:45
XXX.XXX.Startup.Configuration(IAppBuilder app) in
D:\xxx\xxx\xxx\Startup.cs:16
[TargetInvocationException: Exception has been thrown by the target of
aninvocation.] System.RuntimeMethodHandle.InvokeMethod(Object
target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,
Object[] parameters, Object[] arguments) +128
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags
invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+146 Owin.Loader.<>c__DisplayClass12.b__b(IAppBuilder builder) +93
Owin.Loader.<>c__DisplayClass1.b__0(IAppBuilder
builder) +209
Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action 1
startup) +843
Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action 1 startup) +51
Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint()
+101 System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func 1 valueFactory)
+141 Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication
context) +172
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr
appContext, HttpContext context, MethodInfo[] handlers) +618
System.Web.HttpApplication.InitSpecial(HttpApplicationState state,
MethodInfo[] handlers, IntPtr appContext, HttpContext context) +172
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr
appContext, HttpContext context) +419
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr
appContext) +343
[HttpException (0x80004005): Exception has been thrown by the target
of an invocation.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +579
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context)
+120 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest
wr, HttpContext context) +712
Here is the code I have (NLP.Start() is called in startup.cs):
public static class NLP
{
private static string _modelLocation = #"~\NLPModels";
public static string ModelLocation
{
set
{
NLP.Start(value);
}
get
{
return _modelLocation;
}
}
private static StanfordCoreNLP pipeline;
public static void Start(string modelLocation = null)
{
var curDir = Environment.CurrentDirectory;
if (!string.IsNullOrEmpty(modelLocation))
{
_modelLocation = modelLocation;
}
try
{
// Annotation pipeline configuration
var props = new Properties();
props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref");
props.setProperty("sutime.binders", "0");
// We should change current directory, so StanfordCoreNLP could find all the model files automatically
Directory.SetCurrentDirectory(HostingEnvironment.MapPath(ModelLocation));
pipeline = new StanfordCoreNLP(props);
}
finally
{
Directory.SetCurrentDirectory(curDir);
}
}
public static JObject ProcessText(string text)
{
var annotation = new Annotation(text);
using (java.io.StringWriter writer = new java.io.StringWriter())
{
pipeline.jsonPrint(annotation, writer);
return JObject.Parse(writer.toString());
}
}
}
After poking around a bit, I found the solution of the same problem.
https://github.com/sergey-tihon/Stanford.NLP.NET/issues/11
If you aren't willing to read through the thread, here was the basic answer. Amend this line of code
props.setProperty("sutime.binders", "0");
to
props.setProperty("ner.useSUTime", "0");

Controller Action ambiguity even with [HttpPost] attribute? (ASP.NET MVC4)

So I have a "Register" view (that maps to a RegisterController), which is a simple form for people to register in my service. Given that the form's method is POST, then I can name both actions of the controller (the one that shows the form, and the one that receives its submission) the same name, but discriminate them via the [HttpPost] attribute, this way:
open System
open System.Web
open System.Web.Mvc
open System.Net
open System.Threading
open System.Configuration
[<HandleError>]
type RegisterController() =
inherit Controller()
member this.Index (guid: string) =
let model = new RegisterModel(guid)
this.View("Register", model) :> ActionResult
[<HttpPost>]
member this.Index
(guid: string, password: string, passwordRetry: string) =
if not (password.Equals(passwordRetry)) then
raise(new Exception("Passwords must be the same"))
WebDbAccess.SetNewPassword guid password
RedirectResult("/") :> ActionResult
This works perfectly.
However, I just tried to use this same technique in the Home view of my app (for the Login functionality), and it doesn't work! It throws this:
The current request for action 'Index' on controller type 'HomeController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Index(System.String, System.String) on type FsWeb.Controllers.HomeController
System.Web.Mvc.ActionResult Index() on type FsWeb.Controllers.HomeController
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Reflection.AmbiguousMatchException: The current request for action 'Index' on controller type 'HomeController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Index(System.String, System.String) on type FsWeb.Controllers.HomeController
System.Web.Mvc.ActionResult Index() on type FsWeb.Controllers.HomeController
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[AmbiguousMatchException: The current request for action 'Index' on controller type 'HomeController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Index(System.String, System.String) on type FsWeb.Controllers.HomeController
System.Web.Mvc.ActionResult Index() on type FsWeb.Controllers.HomeController]
System.Web.Mvc.Async.AsyncActionMethodSelector.FindAction(ControllerContext controllerContext, String actionName) +495852
System.Web.Mvc.Async.ReflectedAsyncControllerDescriptor.FindAction(ControllerContext controllerContext, String actionName) +57
System.Web.Mvc.ControllerActionInvoker.FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, String actionName) +16
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +114
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929
What's the difference between the 2 cases? I don't get it.
The HomeController's implementation is:
open System
open System.Web
open System.Web.Http
[<HandleError>]
type HomeController() =
inherit Controller()
[<HttpGet>]
member this.Index () =
this.View() :> ActionResult
[<HttpPost>]
member this.Index
(id:string, password:string) =
if (UserIsValid id password) then
RedirectResult("lobby") :> ActionResult
RedirectResult("loginError") :> ActionResult
#nemesv was right, I had to fully qualify HttpPost with System.Web.Mvc.HttpPost because otherwise it would use System.Web.Http.HttpPost!!

Post error: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage

Any post in my Asp.net MVC generate this error:
Server Error in '/' Application.
Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.] System.Web.HttpRequest.GetEntireRawContent() +12673515 System.Web.HttpRequest.get_InputStream() +61 System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) +132 System.Web.Mvc.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory) +28 System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +248 System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +165 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536 System.Linq.Enumerable.ToList(IEnumerable`1 source) +80 System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) +343 System.Web.Mvc.ControllerBase.get_ValueProvider() +57 System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +81 System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +153 System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +839919 System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag) +27 System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +50 System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166 System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +827009 System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27 System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +401 System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +787114 System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +343 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12622419 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18213
Full error details:
System.InvalidOperationException
Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.
System.InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.
at System.Web.HttpRequest.GetEntireRawContent()
at System.Web.HttpRequest.get_InputStream()
at System.Web.HttpRequestWrapper.get_InputStream()
at System.Web.Mvc.JsonValueProviderFactory.GetDeserializedObject(ControllerContext controllerContext)
at System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at Castle.Proxies.Invocations.ValueProviderFactory_GetValueProvider.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Core.Extensibility.CastleInvocationToAlternateMethodContextAdapter.Proceed()
at Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult)
at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
at Glimpse.Core.Extensibility.AlternateTypeToCastleInterceptorAdapter.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ValueProviderFactoryProxy.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ControllerBase.get_ValueProvider()
at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Route config:
Default
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "home", action = "index", id = UrlParameter.Optional },
namespaces: new string[] { "CreditoImobiliarioBB.Web.Controllers" }
);
}
Areas
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Usuario_default"
,"usuario/{controller}/{action}/{id}"
,new { controller="home", action = "index", id = UrlParameter.Optional }
, namespaces: new string[] { "CreditoImobiliarioBB.Web.Areas.Usuario.Controllers" }
);
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Relatorios",
url: "{controller}/{id}/relatorio/{action}",
defaults: new { id = 1 },
constraints: new { id = #"^\d+$" },
namespaces: new string[] { "CreditoImobiliarioBB.Web.Areas.Relatorios" }
);
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Documentos",
url: "{controller}/{id}/documento/{action}",
defaults: null,
constraints: new { id = #"^\d+$" }
);
}
Just posting the findings here - as a summary of the chat - since others may get this error. Don't hand out bounty, since I didn't actually find the solution. ;-)
The error itself is a result of trying to access BinaryRead, Form, Files or InputStream after something else has already accessed the request entity body stream (in other words, the content of the request) using a different method.
These "different methods" seem to include GetBufferedInputStream and GetBufferlessInputStream. These methods appear (not sure) to all be mutually exclusive. In other words, for a single request, you can only use one of:
BinaryRead(), Form, Files, InputStream (these will "cooperate" with each other),
GetBufferedInputStream(), or
GetBufferlessInputStream()
GetBufferedInputStream should cooperate with the "classic" access methods, according to the documentation - in fact, that's its only difference from GetBufferlessInputStream. Nonetheless, in this case, the error stems from GetBufferedInputStream() being used, followed by InputStream.
The different methods are (inadequately) described in the documentation for the ReadEntityBodyMode property and its enum type.
A recent commit to the ASP.NET WebAPI changed its method of reading the body entity to GetBufferedInputStream() where before it used request.InputStream.
This appears to conflict with MVC's JsonValueProviderFactory.GetDeserializedObject which uses the "classic" InputStream property to read the entity body. If we take the error message at face value, GetBufferedInputStream() has already been called, but it isn't done reading when InputStream is accessed, so InputStream hasn't been filled yet.
Need to do more testing, but a temporary fix (found by #KiranChalla) is to revert to a build from before the above-mentioned commit.
We've reverted to using request.InputStream in Web API due to this problem (commit 9c76bb9090490541a453fcead75485ea50b88022).
JimmiTh's answer correctly notes a discrepancy between the initial release notes and the implementation. As implied in the later documentation mentioned above (though it is not particularly clear), request.GetBufferlessInputStream(), request.GetBufferedInputStream() and request.InputStream (along with Form, Files, etc.) are three mutually exclusive methods of request body access.
It appears that, contrary to the initial release notes, request.GetBufferedInputStream() is not currently usable unless no other callers for the same request use any of InputStream, Form, Files, etc. I'm also following up to see if something better can be done compatibility between these two methods.
David
An update after talking with the product team:
Calling request.GetBufferedInputStream() or request.GetBufferlessInputStream() means "I'm handling the stream explicitly myself; take me into advanced mode where automatic stream processing is disabled." However, in the case of buffered only, the members that normally rely on automatic stream processing (Form, Files, InputStream, etc.) are re-enabled after the buffered stream has been fully read.
So, as the exception message hints, touching any of those properties before finishing reading the stream will fail:
public ActionResult Index()
{
Request.GetBufferedInputStream();
var ignore = Request.InputStream;
return View();
}
But doing so after finishing reading the stream will succeed:
public ActionResult Index()
{
var stream = Request.GetBufferedInputStream();
new StreamReader(stream).ReadToEnd();
var ignore = Request.InputStream;
return View();
}
The documentation isn't particularly clear here; I'll ask the product team if they can improve it.
We're planning on switching back to GetBufferedInputStream in Web API; we'll just make sure it plays better with MVC in terms of when this call happens relative to consuming the stream and MVC executing.
I had the same issue when uploading files via Web API. Apparently "maximum request length exceeded" was hiding beneath this error, so increasing maxRequestLength in web.config solved it in my case.
Today I learned that if you are using WebApi and your stream is a System.Net.Http.StreamContent.ReadOnlyStream and you try and read 0 bytes from it (stream.Read(buffer, 0, 0)), it will throw a System.InvalidOperationException, which when caught in a try/catch will show up as an exception with the message "Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream."
I realize this seems silly, but you can do the same thing on a memory stream or file stream and no exception is thrown and in my case it was coming from MsgPackCli, hopefully this saves someone 4 hours.

ASP.NET MVC 4, The "WebSecurity.InitializeDatabaseConnection" method can be called only once

I am developing a code first web app in Visual Studio 2012 Express.
I use this connection string in the web.config:
<add name="myContext" connectionString="Data Source=.;Integrated Security=True;Initial Catalog=cityKingMVC4" providerName="System.Data.SqlClient" />
I am using SimpleMembership.
I am trying to seed 1 administrator from Filters/InitializeSimpleMembershipAttribute.cs:
...
WebSecurity.InitializeDatabaseConnection("myContext", "Users", "UserId", "Email", autoCreateTables: true);
// A: Create Admin user
if (!WebSecurity.ConfirmAccount("admin#mydom.com"))
{
WebSecurity.CreateUserAndAccount("admin#mydom.com", "password");
}
// B: Create admin role if not exist
if (!Roles.RoleExists("Administrator"))
{
Roles.CreateRole("Administrator");
Roles.AddUserToRole("admin#mydom.com", "Administrator");
}
If I comment A & B it doesn't crash. If I don't I get this:
The "WebSecurity.InitializeDatabaseConnection" method can be called only once.
If I debug and put a breakpoint on 'WebSecurity.InitializeDatabaseConnection' - it only calls it once and there is no other code calling WebSecurity.InitializeDatabaseConnection anywhere.
If I debug - it crashes on a different line higher up in the file (standard SimpleAuthentication file):
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
with this error:
Exception has been thrown by the target of an invocation.
Stack Trace:
[InvalidOperationException: The "WebSecurity.InitializeDatabaseConnection" method can be called only once.]
WebMatrix.WebData.WebSecurity.InitializeMembershipProvider(SimpleMembershipProvider simpleMembership, DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean createTables) +87978
WebMatrix.WebData.WebSecurity.InitializeProviders(DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables) +86
myapPMVC4.Filters.SimpleMembershipInitializer..ctor() in c:\Users\name\Documents\Visual Studio 2012\Projects\myapPMVC4\myapPMVC4\Filters\InitializeSimpleMembershipAttribute.cs:43
[InvalidOperationException: The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588]
myapPMVC4.Filters.SimpleMembershipInitializer..ctor() in c:\Users\name\Documents\Visual Studio 2012\Projects\myapPMVC4\myapPMVC4\Filters\InitializeSimpleMembershipAttribute.cs:88
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256
System.Activator.CreateInstance(Type type, Boolean nonPublic) +127
System.Activator.CreateInstance(Type type) +11
System.Threading.LazyHelpers`1.ActivatorFactorySelector() +72
System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +241
System.Threading.LazyInitializer.EnsureInitialized(T& target, Boolean& initialized, Object& syncLock) +139
myapPMVC4.Filters.InitializeSimpleMembershipAttribute.OnActionExecuting(ActionExecutingContext filterContext) in c:\Users\name\Documents\Visual Studio 2012\Projects\myapPMVC4\myapPMVC4\Filters\InitializeSimpleMembershipAttribute.cs:22
System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +145
System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +840201
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__31(AsyncCallback asyncCallback, Object asyncState) +266
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +202
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag) +112
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +839055
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag) +27
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +50
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +826145
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +401
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +786250
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +343
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12550291
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
What's going on?
Thx
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Web.Mvc;
using WebMatrix.WebData;
using System.Web.Security;
using myapPMVC4.Models;
namespace myapPMVC4.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
//WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("myapPMVC4DBContext", "Users", "UserId", "Email", autoCreateTables: true);
}
// Create Admin user
if (!WebSecurity.ConfirmAccount("admin#myapp.com"))
{
//WebSecurity.CreateUserAndAccount("admin", "pass", new { email = "a#b.com" });
WebSecurity.CreateUserAndAccount("admin#myapp.com", "pass");
}
// Create admin role if not exist
if (!Roles.RoleExists("Administrator"))
{
Roles.CreateRole("Administrator");
Roles.AddUserToRole("admin#myapp.com", "Administrator");
}
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
}
The problem ...
is that InitializeDatabaseConnection calls WebSecurity.InitializeProviders internally, and this method is not thread-safe, then combine this with the fact that WebSecurity typically needs initializing from various places. This has implications as web applications are inherently multi-threaded environments ... and WebSecurity.Initialized and WebSecurity.InitializeDatabaseConnection are not thread-safe when used together - they create a typical race condition.
Seeding (for migrations) means that your WebSecurity can be initialized more than once as you may also need to initialise it in Global.asax.cs for deployments with seeding turned off, and your InitializeSimpleMembershipAttribute can potentially be called multiple times simultaneusly by http requests in live deployments etc.
Putting the initialisation code in multiple places also breaks your DRYness
The solution ...
Make sure your init calls are thread-safe, and only occur once per instance of an AppDomain. Use a thread-safe singleton class to do this; and reduce duplication of code.
Call the singleton's EnsureInitialize method from any/all of the following, as appropriate for your application:
Global.asax.cs (Application_Start method before anything else)
Migrations\Configuration.cs Seed method (before creating the users)
Filters\InitializeSimpleMembershipAttribute.cs (in the SimpleMembershipInitializer constructor after the context is initialised)
Here is a simple example singleton:
// Call this with WebSecurityInitializer.Instance.EnsureInitialize()
public class WebSecurityInitializer {
private WebSecurityInitializer() { }
public static readonly WebSecurityInitializer Instance = new WebSecurityInitializer();
private bool isNotInit = true;
private readonly object SyncRoot = new object();
public void EnsureInitialize() {
if (isNotInit) {
lock (this.SyncRoot) {
if (isNotInit) {
isNotInit = false;
WebSecurity.InitializeDatabaseConnection("MyContextName",
userTableName: "UserProfile", userIdColumn: "UserId", userNameColumn: "UserName",
autoCreateTables: true);
}
}
}
}
}
Once I had done this, my case of the error you mention disappeared, not to be seen again.
Footnotes
The singleton class also keeps your code DRY, which is especially useful during early stage app development if you need to later change the configuration of your WebSecurity.InitializeDatabaseConnection as it will only be in one place (end edit)
I also keep the SimpleMembershipInitializer clean, and instead seed my users along with the common seeding in Migrations\Configuration.cs Seed method. This helps with testability of seeding through my migrations by keeping everything in one place. I use unit testing to make sure we can always go up and down the migrations tree, so this makes it easier to do that.
However the location of your seeding code won't matter, it is more just making sure that, globally, you have initialised WebSecurity only once within your AppDomain, and that any call to InitializeDatabaseConnection is thread-safe.
Add this code to Global.asax.cs. This will makes sure that your database is always Initialized before any other executions. Also make sure its the first registration in Application_Start()
if (!WebSecurity.Initialized)
WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
Get rid of Filters/InitializeSimpleMembershipAttribute.cs or just comment the code inside, in case you would like to go back to it.
Remove [InitializeSimpleMembership] at the top of AccountController.cs
Also if you haven't already enabled migrations, i would encourage you do so. That way, you can do your seeds in Configuration.cs created inside the Migration folder when you run Enable-Migrations
If it is already initialized then make sure your first call:
if (!WebSecurity.Initialized)
{
// Do the initialization first.
}
// The rest of the code
This way you'll be sure that you don't repeat the initialization process.
Do you also have the InitializeSimpleMembership attribute on your AccountController class? (this is the default). If so, you are initializing twice.
To make sure that the WebSecurity.InitializeDatabaseConnection is not called twice just use the WebSecurity.Initialized to check if it was already called. This blog post provides detailed instructions on seeding and customizing SimpleMembership. There is a series in this blog on using SimpleMembership and I would also recommend looking at decoupling SimpleMembership from your ASP.NET MVC Application. You can get the complete source code for these examples here.

Resources