while overriding Window, I came across a fatal exception:
System.InvalidOperationException: MauiContext is null
I was trying to ovveride Window Class so that everytime the app is open or closed I use messenger to notify the base class to logout the user and request verification to login back.
This is my class where I inherit from Window. And in App.xaml.cs I ovveride it and returning MyWindow using as a parameter MainPage.
I think that when App is in the background and then opened again there is an issue. So guidance on how to handle this exception?
public class Message : ValueChangedMessage<string>
{
public Message(string message) : base(message)
{
}
}
public class MyWindow : Window
{
public MyWindow() : base()
{
}
public MyWindow(Page page) : base(page)
{
}
protected override void OnStopped()
{
WeakReferenceMessenger.Default.Send(new Message("Stopped"));
}
protected override void OnResumed()
{
WeakReferenceMessenger.Default.Send(new Message("Resumed"));
}
protected override MyWindow CreateWindow(IActivationState activationState)
{
return new MyWindow(MainPage);
}
Fatal Exception: android.runtime.JavaProxyThrowable:
System.InvalidOperationException: MauiContext is null.
at Microsoft.Maui.Controls.Window.get_MauiContext()
at Microsoft.Maui.Controls.Platform.AlertManager.Subscribe(Window window)
at Microsoft.Maui.Controls.Platform.AlertManager.Subscribe()
at Microsoft.Maui.Controls.Window.<>c__DisplayClass206_0.g__OnPageHandlerChanged|0(Object sender, EventArgs e)
at Microsoft.Maui.Controls.Window.OnPageChanged(BindableObject bindable, Object oldValue, Object newValue)
at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
at Microsoft.Maui.Controls.Window.set_Page(Page value)
at Microsoft.Maui.Controls.Window..ctor(Page page)
at name.ViewModels.MyWindow..ctor(Page page)
at name.App.CreateWindow(IActivationState activationState)
at Microsoft.Maui.Controls.Application.Microsoft.Maui.IApplication.CreateWindow(IActivationState activationState)
at Microsoft.Maui.Platform.ApplicationExtensions.CreatePlatformWindow(Activity activity, IApplication application, Bundle savedInstanceState)
at Microsoft.Maui.MauiAppCompatActivity.OnCreate(Bundle savedInstanceState)
at name.MainActivity.OnCreate(Bundle savedInstanceState)
at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(IntPtr , IntPtr , IntPtr )
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V , IntPtr , IntPtr , IntPtr )
at crc64790243dcc0ae3d15.MainActivity.n_onCreate(MainActivity.java)
at crc64790243dcc0ae3d15.MainActivity.onCreate(MainActivity.java:40)
at android.app.Activity.performCreate(Activity.java:7994)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1534)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3439)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3632)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7701)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)`
Related
I have an AppCompatActivity that has 3 tabs using FragmentTabHost. One of the tabs uses LocationServices. I would like to have the smoothest possible user experience:
If the LocationService is off in the android system, and only if the user chooses the tab that needs the Location I would like to display the AlertDialog to let the user turn on the Location in the system settings.
I have a helper class that is supposed to do all this and it does work in 3 other places in my app. In those 3 places it works "directly" in the Activity, however in this place it needs to work "within" the Fragment of the tab.
The problem is that if I have the line:
builder.enableAutoManage(activity, 0, this);
then builder.build() throws an exception: IllegalStateException: Recursive entry to executePendingTransactions
Any idea how can I achieve my goal?
Here are some related code fragments:
public class CityPreferences extends AppCompatActivity {
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(
mTabHost.newTabSpec("available_cities")
.setIndicator(getString(R.string.tab_all_cities))
, AvailableCityFragment.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("nearby_cities")
.setIndicator(getString(R.string.tab_nearby_cities))
, NearbyCityFragment.class, null);
}
}
In NearbyCityFragment I have this 1 line of code:
class NearbyCityFragment extends Fragment {
...
LocationServiceHelper.getInstance().startOrDisplayDialog(getActivity());
(I tried it in onAttach, onStart, onResume)
And here's my helper class' function:
public class LocationServiceHelper implements
GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks {
public boolean startOrDisplayDialog(#NonNull final FragmentActivity activity) {
final boolean servicesConnected = GooglePlayServicesHelper.checkOrDisplayDialog(activity);
if (servicesConnected) {
final boolean isEnabled = isLocationEnabledInSystem(activity);
if (isEnabled) {
if (null == mGoogleApiClient) {
mContext = activity;
mActivity = activity;
final GoogleApiClient.Builder builder = new GoogleApiClient.Builder(mContext)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this);
// the next line seems to cause the problem:
builder.enableAutoManage(activity, 0, this);
mGoogleApiClient = builder
.build();
}
return start();
} else {
final Dialog dialog = getLocationDisabledDialog(activity);
GooglePlayServicesHelper.showDialog(dialog, activity);
}
}
return false;
}
And finally the exception:
06-10 10:23:04.831 26725-26725/com.fletech.android.redalert.debug E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.fletech.android.redalert.debug, PID: 26725
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1473)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
at com.google.android.gms.common.api.g.a(Unknown Source)
at com.google.android.gms.common.api.GoogleApiClient$Builder.gI(Unknown Source)
at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source)
at com.fletech.android.redalert.helper.LocationServiceHelper.startOrDisplayDialog(LocationServiceHelper.java:113)
at com.fletech.android.redalert.city.NearbyCityFragment.onAttach(NearbyCityFragment.java:44)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:907)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I believe you must use a unique clientId each time you enable auto manager. From the documentation:
clientId - A non-negative identifier for this client. At any given time, only one auto-managed client is allowed per id. To reuse an id you must first call stopAutoManage(FragmentActivity) on the previous client.
we use a StateServer for handling Session for the known benefits (web farm, IIS recycling).
However I am trying to figure out how to make this fault tolerant. Nothing we store in the Session is critical, it is just used for performance. So if the StateServer is not available we are happy to reload from disk.
However there appears to be no way of detecting if the StateServer is online or not, so the following code all runs fine even if the StateServer is down
try
{
//It is not NULL as it has been configured
if (HttpContext.Current.Session != null)
Session["Test"] = "value";
}
// No exception is thrown
catch (Exception)
{
throw new Exception();
}
Now it makes sense to me that no exception is thrown. The Session handling would not be very performant if it had to check the status on every write. So I am guessing what happens is that it writes all the Session vaiables when the Response is written.
There lies the problem, when it tries to write the Session it fails with a 500 error and I do not know anyway to intercept this error and handle it.
Unable to make the session state request to the session state server.
Please ensure that the ASP.NET State service is started and that the
client and server ports are the same.
What I would like to happen is that the write just fails silently (or logs an error) and clients are not impacted. As it is write now the entire site goes down due to this single point of failure.
Any ideas - am I missing something obvious?
well, it can be hard. Asp.net uses session tightly, so if session storage fails, it asp.net will also fails during initialization of session module. You can write own session state provider, that will wrap existing one, and in case of fail it will return empty session items, but it can be hard to use it, because session behavior can be unpredictable.
You can look into built in SQL session state provider, that has failover in case if your SQL server has replication.
UPDATE1
Here is example of wrapper for default session providers
public class SessionProviderWrapper : SessionStateStoreProviderBase
{
private readonly SessionStateStoreProviderBase _provider;
private static Func<SessionStateStoreProviderBase> _createProvider;
static SessionProvider()
{
_createProvider = InitializerProvider();
}
private static Func<SessionStateStoreProviderBase> InitializerProvider()
{
if (_createProvider != null)
return _createProvider;
var sessionType = "stateserver"; // you can switch to another session provider
Type type;
switch (sessionType)
{
case "inproc":
type = Type.GetType("System.Web.SessionState.InProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "sql":
type = Type.GetType("System.Web.SessionState.SqlSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "stateserver":
type = Type.GetType("System.Web.SessionState.OutOfProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
default:
throw new ConfigurationErrorsException("Unknow session type: " + sessionType);
}
if (type == null)
{
throw new InvalidOperationException("Failed to find session provider for " + sessionType);
}
_createProvider = GenerateConstructorCall(type);
return _createProvider;
}
private static Func<SessionStateStoreProviderBase> GenerateConstructorCall(Type type)
{
// we are searching for public constructor
var constructor = type.GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0);
if (constructor == null)
{
// otherwise for internal. SQL session provider has internal constructor, but we don't care
constructor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Length == 0);
}
var node = Expression.New(constructor);
var lambda = Expression.Lambda<Func<SessionStateStoreProviderBase>>(node, null);
var func = lambda.Compile();
return func;
}
public SessionProvider()
{
var createProvider = InitializerProvider();
_provider = createProvider();
}
public override void Initialize(string name, NameValueCollection config)
{
_provider.Initialize(name, config);
}
public override string Name
{
get { return _provider.Name; }
}
public override string Description
{
get { return _provider.Description; }
}
public override void Dispose()
{
_provider.Dispose();
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return _provider.SetItemExpireCallback(expireCallback);
}
public override void InitializeRequest(HttpContext context)
{
_provider.InitializeRequest(context);
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
try
{
return _provider.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
}
catch (Exception ex)
{
locked = false;
lockAge = TimeSpan.Zero;
lockId = null;
actions = SessionStateActions.None;
// log ex
return new SessionStateStoreData(new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 10);
}
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
return _provider.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
_provider.ReleaseItemExclusive(context, id, lockId);
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
_provider.SetAndReleaseItemExclusive(context, id, item, lockId, newItem);
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
_provider.RemoveItem(context, id, lockId, item);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
_provider.ResetItemTimeout(context, id);
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return _provider.CreateNewStoreData(context, timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
_provider.CreateUninitializedItem(context, id, timeout);
}
public override void EndRequest(HttpContext context)
{
_provider.EndRequest(context);
}
}
Basically you can make try\catch on each method like in GetItem method, and in case of error, you can return empty session object. If it fails in try\catch application still will be alive. But performance will be decreased as for each request it will throw a couple of exceptions on Get\Release, that will be handled in catch section. But anyway these exceptions will decrease performance a bit
I would like to accept tgolisch answer as a solution that works for me.
In Global.asax we will look for the missing StateServer error in the Application_Error event
If we find it we will use Server.ClearError() and log the error
We will also use this to log the error and possibly send out an alert
Thanks all!
Strange exception, this was working fine before.
System.InvalidCastException: Cannot convert object 'Waiting' to type 'System.Activities.Statements.Pick+PickState'.
at System.Runtime.TypeHelper.Convert[T](Object source)
at System.Activities.Location`1.set_ValueCore(Object value)
at System.Activities.ActivityContext.SetValueCore[T](LocationReference locationReference, T value)
at System.Activities.ActivityContext.SetValue[T](OutArgument`1 argument, T value)
at System.Activities.OutArgument`1.Set(ActivityContext context, T value)
at MyApplication.WaitForStatusChange.OnBookmarkResumed(NativeActivityContext context, Bookmark bookmark, Object value)
at System.Activities.Runtime.BookmarkCallbackWrapper.Invoke(NativeActivityContext context, Bookmark bookmark, Object value)
at System.Activities.Runtime.BookmarkWorkItem.Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
MyApplication.WaitForStatusChange is a custom NativeActivity, the error occurs when the workflow is resumed on the bookmark for this activity, whith an enum for bookmar argument.
The WaitForStatusChange activity is placed inside a Pick activity (with another NativeActivity on the other branch)
Activity code
public class WaitForPartnerIntegrationStatusChange : NativeActivity
{
public OutArgument<PartnerSoftwareIntegrationStatus> Status { get; set; }
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark(DocumentStatusChangeWatcher.DocumentPartnerSoftwareIntegrationStatusChangedBookmark, OnBookmarkResumed);
}
private void OnBookmarkResumed(NativeActivityContext context, Bookmark bookmark, object value)
{
if (value is PartnerSoftwareIntegrationStatus)
{
Status.Set(context, (PartnerSoftwareIntegrationStatus)value);
}
}
protected override bool CanInduceIdle
{
get { return true; }
}
}
You see these kinds of strange exceptions often when you make a change to a workflow definition and try to resume a persisted workflow.
Basically you can't make any changes to running workflows.
It doesn't happen often but from time to time I'll get an exception report emailed to me pointing to this bit of code. I'm wondering if you see anything wrong with the following code. I cannot get it to fail locally and tracing the data using breakpoints always gives the correct results, step by step.
namespace DomainModel.Concrete
{
public class ConfigRepository : IConfigRepository
{
static mvCmsContext context { get; set; }
public ConfigRepository() { context = new mvCmsContext(); }
private static Func<mvCmsContext, string, Configuration> _byName =
CompiledQuery.Compile((mvCmsContext context, string configName) =>
(from c in context.Configs
where c.configName == configName
select c).SingleOrDefault());
static public Configuration ByName(string configName)
{
var result = (Configuration)HttpContext.Current.Cache.Get(configName);
if (result == null)
{
using (new mvCmsContext())
{
HttpContext.Current.Cache.Insert(configName, _byName(context, configName));
result = (Configuration)HttpContext.Current.Cache.Get(configName);
}
}
return result;
}
}
}
Here is the service calling that method:
public class ConfigService
{
public static string siteName
{
get { return ConfigRepository.ByName("Site_Name").configValue; }
}
public static string copyright
{
get { return ConfigRepository.ByName("Copyright").configValue; }
}
public static string companyName
{
get { return ConfigRepository.ByName("Company_Name").configValue; }
}
public static string homeTitle
{
get { return ConfigRepository.ByName("Home_Title").configValue; }
}
public static string contactEmail
{
get { return ConfigRepository.ByName("Contact_Email").configValue; }
}
public static string physicalAddress
{
get { return ConfigRepository.ByName("Physical_Address").configValue; }
}
public static string phoneNumber
{
get { return ConfigRepository.ByName("Phone_Number").configValue; }
}
}
Here is the report received:
** Summary **
--------------- This message contains events 1 to 1 from the total of 1
events scheduled for this
notification. There were 0 events
left in the buffer at the beginning of
this notification.
** Application Information **
--------------- Application domain: /LM/W3SVC/66/ROOT-7-129384226573152341
Trust level: Full Application Virtual
Path: / Application Path:
D:*****.com\ Machine name:
WIN11
** Events **
--------------- Event code: 3005 Event message: An unhandled exception has
occurred. Event time: 1/2/2011
12:17:44 AM Event time (UTC): 1/2/2011
6:17:44 AM Event ID:
f909c5c676bd4ca1ba21512c678ac502 Event
sequence: 6 Event occurrence: 1 Event
detail code: 0
Process information:
Process ID: 26904
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE
Exception information:
Exception type: System.InvalidOperationException
Exception message: Invalid operation. The connection is closed.
Request information:
Request URL: http://.com/article/-ALERT
Request path: /article/III-ALERT
User host address: 68.230.129.53
User:
Is authenticated: False
Authentication Type:
Thread account name: NT AUTHORITY\NETWORK SERVICE
Thread information:
Thread ID: 6
Thread account name: NT AUTHORITY\NETWORK SERVICE
Is impersonating: False
Stack trace: at System.Data.SqlClient.SqlConnection.GetOpenConnection()
at
System.Data.SqlClient.SqlConnection.get_HasLocalTransactionFromAPI()
at
System.Data.SqlClient.SqlCommand.ValidateCommand(String
method, Boolean async) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior,
Boolean returnStream, String method,
DbAsyncResult result) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior,
Boolean returnStream, String method)
at
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
behavior, String method) at
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior
behavior) at
System.Data.Linq.SqlClient.SqlProvider.Execute(Expression
query, QueryInfo queryInfo,
IObjectReaderFactory factory, Object[]
parentArgs, Object[] userArgs,
ICompiledSubQuery[] subQueries, Object
lastResult) at
System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression
query, QueryInfo[] queryInfos,
IObjectReaderFactory factory, Object[]
userArguments, ICompiledSubQuery[]
subQueries) at
System.Data.Linq.SqlClient.SqlProvider.CompiledQuery.Execute(IProvider
provider, Object[] arguments) at
System.Data.Linq.CompiledQuery.ExecuteQuery(DataContext
context, Object[] args) at
System.Data.Linq.CompiledQuery.Invoke[TArg0,TArg1,TResult](TArg0
arg0, TArg1 arg1) at
DomainModel.Concrete.ConfigRepository.ByName(String
configName) at
DomainModel.Services.ConfigService.get_companyName()
at
ASP.views_shared_site_master._Render_control1(HtmlTextWriter
__w, Control parameterContainer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter
writer, ICollection children) at
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter
writer, ICollection children) at
System.Web.UI.Page.Render(HtmlTextWriter
writer) at
System.Web.Mvc.ViewPage.Render(HtmlTextWriter
writer) at
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean
includeStagesAfterAsyncPoint)
If I were closing the datacontext at the wrong place it would fail all the time, wouldn't it?
Edit - Data context:
public class mvCmsContext : DataContext
{
public mvCmsContext():
base(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString,XmlMappingSource.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("DomainModel.mvCmsMapping.map"))){
Log = (StringWriter)HttpContext.Current.Items["linqToSqlLog"];
}
public Table<DomainModel.Entities.Configuration> Configs { get { return this.GetTable<DomainModel.Entities.Configuration>(); } }
}
Edit to add update:
Does this look better? I'll upload it and give it a go.
public class ConfigRepository : IConfigRepository
{
private mvCmsContext context { get; set; }
public ConfigRepository() { context = new mvCmsContext(); }
private static Func<mvCmsContext, string, Configuration> _byName =
CompiledQuery.Compile((mvCmsContext context, string configName) =>
(from c in context.Configs
where c.configName == configName
select c).SingleOrDefault());
static public Configuration ByName(string configName)
{
var result = (Configuration)HttpContext.Current.Cache.Get(configName);
if (result == null)
{
using (var context = new mvCmsContext())
{
HttpContext.Current.Cache.Insert(configName, _byName(context, configName));
result = (Configuration)HttpContext.Current.Cache.Get(configName);
}
}
return result;
}
Your issue is that you are defining your datacontext as static. This means its shared by all requests and threads.
When you have two different requests hitting your static datacontext, these sort of exceptions occur. Your using section in ByName will recreate and dispose of the datacontext, imagine another request is using the datacontext while your doing this....... hence the exceptions.
The solution is to make your datacontext non-static.
I have a library assembly that outputs trace information, and a client winforms application that adds a trace listener via app.config. If I were to use the library in ASP.NET, not configured for System.Diagnostics tracing, how could I 'catch' the trace output?
Bonus question: Can I do something with Elmah to catch and log this info? Our ASP.NET app currently uses Elmah for error logging, but that's all I know on that side of things.
I think that, as long as the library outputs trace information, this information could be captured with any specialized tool (like DebugView) or even a house grown tool, regardless of ASP.NET configuration.
I see this is old and answered, but.. I have just had the same issue and I came up with
Exception class for tracelistener
namespace TrueNorth.Elmah.TraceListener
{
internal class TraceInformation : Exception
{
internal TraceInformation(string message) : base(message){}
}
internal class TraceError: Exception
{
internal TraceError(string message) : base(message) { }
}
internal class TraceWarning : Exception
{
internal TraceWarning(string message) : base(message) { }
}
internal class TraceWrite : Exception
{
internal TraceWrite(string message) : base(message) { }
}
}
The listener
namespace TrueNorth.Elmah.TraceListener
{
internal class ElmahListener : System.Diagnostics.TraceListener
{
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
{
TraceEvent(eventCache, source, eventType, id, string.Format(format, args));
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) //
{
Exception exception;
switch (eventType)
{
case TraceEventType.Information:
exception = new TraceInformation(message);
break;
case TraceEventType.Error:
exception = new TraceError(message);
break;
case TraceEventType.Warning:
exception = new TraceWarning(message);
break;
default:
exception = new TraceWrite(message);
break;
}
if (HttpContext.Current.Session == null)
{
ErrorLog.GetDefault(null).Log(new Error(exception));
}
else
{
ErrorSignal.FromCurrentContext().Raise(exception );
}
}
public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
{
base.TraceTransfer(eventCache, source, id, message, relatedActivityId);
}
public override void Write(string message)
{
}
public override void WriteLine(string message)
{
}
}
}
And, the GO code ( you can use your web.config)
Tracer.Register();
blogged at http://truenorthit.co.uk/2015/04/17/trace-listener-for-elmah-asp-mvc-exception-logger/
write code for attaching a trace file listener programtically and enable tracing in web.config - you will be done after that