<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="RichTextWithBetterSpacing" TargetType="{x:Type RichTextBox}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontFamily" Value="Arial"/>
<Style.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
</Style.Resources>
</Style>
</ResourceDictionary>
Thursday, June 25, 2009
RichTextBox with better spacing
It took a bit of looking around today to figure out how to create a resource file entry to style my RichTextBox so that it doesn't have ridiculous spacing. I found this, which shows how to do it inside the page or window. However, I wanted to put it in a resource file so that I could reuse it. I finally came up with this:
Wednesday, December 10, 2008
Custom RoleProvider notes
I finally completed my custom RoleProvider that uses NHibernate to retrieve data from the database. Below I have listed my notes on this topic.
Issue: My RoleProvider would not work if I overrode the default constructor.
Solution: Override the Initialize method and put your code there instead.
Issue: The RoleProvider class cannot access HttpContext.Current.Session.
Solution: There really isn't a solution. It's just a fact.
Resources:
Issue: My RoleProvider would not work if I overrode the default constructor.
Solution: Override the Initialize method and put your code there instead.
Issue: The RoleProvider class cannot access HttpContext.Current.Session.
Solution: There really isn't a solution. It's just a fact.
Resources:
Custom MembershipProvider notes
I finally completed my custom MembershipProvider that uses NHibernate to retrieve data from the database. Below I have listed my notes on this topic.
Issue: I could not get the "Web Site Administration Tool" to create a user without giving me an error.
Solution: Make sure that the following property returns true:
public override bool RequiresQuestionAndAnswer
If it was false, I would get a generic error that made absolutely no sense:
The following message may help in diagnosing the problem: Exception has been thrown by the target of an invocation. at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Web.Administration.WebAdminMembershipProvider.CallWebAdminMembershipProviderHelperMethodOutParams(String methodName, Object[] parameters, Type[] paramTypes) at System.Web.Administration.WebAdminMembershipProvider.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status) at System.Web.UI.WebControls.CreateUserWizard.AttemptCreateUser() at System.Web.UI.WebControls.CreateUserWizard.OnNextButtonClick(WizardNavigationEventArgs e) at System.Web.UI.WebControls.Wizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.CreateUserWizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.Wizard.WizardChildTable.OnBubbleEvent(Object source, EventArgs args) at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Issue: I ran into a couple of examples that verify the password by unencoding the one in the database and then comparing it to the user's entry.
Solution: I recommend that you do it the same way that Microsoft did it. That is to encode the user's entry and compare it to the encoded database entry. It eliminates the need to have an unencode method.
Other things worth noting:
If you are going to use Encryption encoding (as opposed to clear text or hash encoding), don't forget to generate your own MachineKey. Here are a few link on that topic:
Resources:
Issue: I could not get the "Web Site Administration Tool" to create a user without giving me an error.
Solution: Make sure that the following property returns true:
public override bool RequiresQuestionAndAnswer
If it was false, I would get a generic error that made absolutely no sense:
The following message may help in diagnosing the problem: Exception has been thrown by the target of an invocation. at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Web.Administration.WebAdminMembershipProvider.CallWebAdminMembershipProviderHelperMethodOutParams(String methodName, Object[] parameters, Type[] paramTypes) at System.Web.Administration.WebAdminMembershipProvider.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status) at System.Web.UI.WebControls.CreateUserWizard.AttemptCreateUser() at System.Web.UI.WebControls.CreateUserWizard.OnNextButtonClick(WizardNavigationEventArgs e) at System.Web.UI.WebControls.Wizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.CreateUserWizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.Wizard.WizardChildTable.OnBubbleEvent(Object source, EventArgs args) at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Issue: I ran into a couple of examples that verify the password by unencoding the one in the database and then comparing it to the user's entry.
Solution: I recommend that you do it the same way that Microsoft did it. That is to encode the user's entry and compare it to the encoded database entry. It eliminates the need to have an unencode method.
Other things worth noting:
If you are going to use Encryption encoding (as opposed to clear text or hash encoding), don't forget to generate your own MachineKey. Here are a few link on that topic:
- http://aspnetresources.com/tools/keycreator.aspx
- http://msdn.microsoft.com/en-us/library/ms998288.aspx (see bottom for code example)
Resources:
Thursday, December 4, 2008
WCF & the IIS Require secure channel (ssl) setting
After turning on "Require secure channel (SSL)" on the IIS 6.0 Directory security tab (secure communications dialog), I lost several hours today trying to figure out why my WCF services stopped working and started giving me this error:
[System.ServiceModel.ServiceActivationException] = {"The requested service, 'https://www.Dave.com/DoIt/MyService.svc' could not be activated. See the server's diagnostic trace logs for more information."}
I tried a variety of things, but when I finally broke down and ran the diagnostic trace I got the following:
The service '/DoIt/MyService.svc' cannot be activated due to an exception during compilation. The exception message is: Could not find a base address that matches scheme http for the endpoint with binding MetadataExchangeHttpBinding. Registered base address schemes are [https]..
All my services use https to send data; however, my metadata exchange binding, which I intended to remove/comment out later, use http. When I changed all my metadata exchanged end points to use mexHttpsBinding instead of mexHttpBinding and all my behaviors to use <servicemetadata httpsgetenabled="true"> instead of <servicemetadata httpgetenabled="true">, everything started working again.
I figured that the http endpoints would just be ignored or if accessed permissioned denied because all addresses must use a secure channel (https). It appears that I was wrong and that it causes a compilation error.
[System.ServiceModel.ServiceActivationException] = {"The requested service, 'https://www.Dave.com/DoIt/MyService.svc' could not be activated. See the server's diagnostic trace logs for more information."}
I tried a variety of things, but when I finally broke down and ran the diagnostic trace I got the following:
The service '/DoIt/MyService.svc' cannot be activated due to an exception during compilation. The exception message is: Could not find a base address that matches scheme http for the endpoint with binding MetadataExchangeHttpBinding. Registered base address schemes are [https]..
All my services use https to send data; however, my metadata exchange binding, which I intended to remove/comment out later, use http. When I changed all my metadata exchanged end points to use mexHttpsBinding instead of mexHttpBinding and all my behaviors to use <servicemetadata httpsgetenabled="true"> instead of <servicemetadata httpgetenabled="true">, everything started working again.
I figured that the http endpoints would just be ignored or if accessed permissioned denied because all addresses must use a secure channel (https). It appears that I was wrong and that it causes a compilation error.
Wednesday, July 30, 2008
WCF DateTime field adjusted automatically for time zone
Well, I got bit by DateTime serialization yesterday. Our server is in the U.S. Central Standard Time (CST) zone and our client is in the U.S. Eastern Standard Time (EST) zone. All data saved in the database is relative to the client and NOT the server. So when the client wants to see all data for today, only the date is specified using DateTime.Today. So when the EST client sent a date of 7/29/08 00:00:00 AM to our WCF webservice on the CST server, the date was converted to 7/28/08 11:00:00 PM. The symptom from the client's point of view was that they could never retrieve data for today.
According to Coding Best Practices Using DateTime in the .NET Framework there are several ways to work around this; however, they missed one. If you change your dates so that DateTimeKind is unspecified, the XML serializer will NOT try to convert them. For example, this code will convert a date to DateTimeKind.Unspecified:
References:
According to Coding Best Practices Using DateTime in the .NET Framework there are several ways to work around this; however, they missed one. If you change your dates so that DateTimeKind is unspecified, the XML serializer will NOT try to convert them. For example, this code will convert a date to DateTimeKind.Unspecified:
DateTime newDate = DateTime.SpecifyKind(oldDate, DateTimeKind.Unspecified);
References:
Friday, November 30, 2007
Dispatcher versus SynchronizationContext
Today I had the pleasure of playing with the Dispatcher and SynchronizationContext classes. I found that the Dispatcher class is useful when your sure that you are calling within the context of the user interface thread and the SynchronizationContext is useful when you're not quite sure.
If you obtain your Dispatcher class using the static Dispatcher.CurrentDispatcher method on some non-UI thread and call the BeginInvoke method, nothing will happen (No exception, no warning, nada). However, if you obtain your SynchronizationContext class via the static SynchronizationContext.Current method, it will return null if the thread is not a UI thread. This feedback is extremely useful since it allows you to react to both a UI thread and a non-UI thread accordingly.
Here is an example using the Dispatcher class:
Here is an example using the SynchronizationContext class:
Notes:
If you obtain your Dispatcher class using the static Dispatcher.CurrentDispatcher method on some non-UI thread and call the BeginInvoke method, nothing will happen (No exception, no warning, nada). However, if you obtain your SynchronizationContext class via the static SynchronizationContext.Current method, it will return null if the thread is not a UI thread. This feedback is extremely useful since it allows you to react to both a UI thread and a non-UI thread accordingly.
Here is an example using the Dispatcher class:
using System;
using System.Threading;
using System.Windows.Threading; // WindowsBase.dll
namespace Test
{
public delegate void WriteTextDelegate(string message);
public class DispatcherTest
{
public void Start()
{
// Calling thread determines Dispatcher
m_Dispatcher = Dispatcher.CurrentDispatcher;
if (m_Timer == null)
m_Timer = new Timer(new TimerCallback(WriteText),
null, 1000, 2000);
else m_Timer.Change(1000, 2000);
}
public void Stop()
{
if (m_Timer != null)
m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
}
public event WriteTextDelegate Message;
private Timer m_Timer;
private System.Windows.Threading.Dispatcher m_Dispatcher;
private void WriteText(object state)
{
m_Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new WriteTextDelegate(OnMessage),
DateTime.Now.ToString());
}
private void OnMessage(string message)
{
if (Message != null)
Message(message);
}
}
}
Here is an example using the SynchronizationContext class:
using System;
using System.Threading;
namespace Test
{
public delegate void WriteSomeTextDelegate(string message);
public class SyncTest
{
public void Start()
{
// Calling thread determines SynchronizationContext
m_Context = SynchronizationContext.Current;
if (m_Timer == null)
m_Timer = new Timer(new TimerCallback(WriteText),
null, 1000, 2000);
else m_Timer.Change(1000, 2000);
}
public void Stop()
{
if (m_Timer != null)
m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
}
public event WriteSomeTextDelegate Message;
private System.Threading.Timer m_Timer;
private System.Threading.SynchronizationContext m_Context;
private void WriteText(object state)
{
string message = DateTime.Now.ToString();
if (m_Context != null)
{
m_Context.Post(new SendOrPostCallback(PostCallback), message);
}
else OnMessage(message); // non-UI thread called Start
}
private void OnMessage(string message)
{
if (Message != null)
Message(message);
}
private void PostCallback(object state)
{
if (state is string)
{
OnMessage(state as string);
}
else throw new ArgumentException("State should be a string");
}
}
}
Notes:
- I used Reflector to look inside the WindowsBase.dll; however, I had problems finding the dll. I expected to find it in a directory below the usual location (C:\ Windows\ Microsoft.NET\ Framework\ v3.0); however, it was in this directory: C:\ Program Files\ Reference Assemblies\ Microsoft\ Framework\ v3.0
- WCF: Asynchronous Operations
Friday, November 9, 2007
WCF Security Exception: Timestamp is invalid because its creation time is in the future
Well, I ran into a real fun bug today that surfaced itself on the user's computer as a "Security Exception see Inner Exception". Upon examining the inner exception, it told me that the message was incorrectly secured. After placing some tracing on the server, I found this error message:
The security timestamp is invalid because its creation time ('11/9/2007 10:37:07 PM') is in the future. Current time is '11/9/2007 10:28:52 PM' and allowed clock skew is '00:05:00'.
After fixing the user's clock, which was roughly 8 minutes fast, everything worked great. The next question is "How do I increase the maximum skew time"? It took a bit of searching to figure out that I need to create a custom binding to change the values. Here is an example of how to do it:
For more information, see How To: Set a Max Clock Skew on MSDN.
More References:
The security timestamp is invalid because its creation time ('11/9/2007 10:37:07 PM') is in the future. Current time is '11/9/2007 10:28:52 PM' and allowed clock skew is '00:05:00'.
After fixing the user's clock, which was roughly 8 minutes fast, everything worked great. The next question is "How do I increase the maximum skew time"? It took a bit of searching to figure out that I need to create a custom binding to change the values. Here is an example of how to do it:
<bindings>
<customBinding>
<binding name="MaxClockSkewBinding">
<textMessageEncoding />
<security authenticationMode="Kerberos">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap />
</security>
<httpTransport />
</binding>
</customBinding>
</bindings>
For more information, see How To: Set a Max Clock Skew on MSDN.
More References:
- Custom Bindings page on MSDN shows the proper way to stack your collection of binding elements.
- How To: Create a Custom Binding Using the SecurityBindingElement which shows how to build the a custom binding.
Subscribe to:
Posts (Atom)