tag:blogger.com,1999:blog-78327820127250425492024-03-08T00:21:14.357-08:00Karma Garda's Snippet DiaryKarma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-7832782012725042549.post-32201425676297635642012-02-13T03:53:00.001-08:002012-02-13T07:10:19.583-08:00New blog...I'm retiring this blog as it is linked to an old email address. New blog is here: <a href="http://conorssnippetdiary.blogspot.com/">http://conorssnippetdiary.blogspot.com/</a>Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-4349257947988127802012-02-02T04:47:00.001-08:002012-02-13T03:53:04.534-08:00Convention over Configuration - Case sensitivity?Today I had a debate with a fellow employee about the naming conventions of some fields on a CRM form. It's a slightly off the norm of "convention vs configuration" arguments, instead it was more of a "Convention A vs Convention B" type argument. Take this example, the particular field that was added was a web resource. For other reasons we have some javascript that passes over the form to try locate these web resources. I designed the javascript so that it will always look for web resources with the following naming convention for specific web resources:<br /><br />WebResource_DS*<br /><br />So, if we follow this convention we don't need to configure anything. Note that DS is a recognised acronym in our organisation. Unfortunately we ran into some problems in our testing environment, some of the controls weren't being detected. I take a look at the controls and they've been named:<br /><br />WebResource_ds*<br /><br />Now, my gut reaction is to fix the script to allow for case sensitivity... but after a quick think this feels wrong to me. If we're following convention shouldn't it be case sensitive? For example, if we introduce camel casing on database field names then "productname" is incorrect, it should read "productName".<br /><br />So instead of changing it I argued that it should follow the convention of _DS including upper case. I argued that if you follow "convention over configuration" it should include case sensitivity. This should be especially the case for known acronyms (if the convention states all upper-case for acronyms). The debate that he put forward is if you've ever read something like "the design of everyday things" everything should be intuitive, so 'DS' or 'ds' shouldn't matter.<br /><br />I see his point... but I stick by my guns!Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-26955855920708205172011-12-05T08:37:00.000-08:002011-12-05T08:55:00.063-08:00Mocking out Environment.ExitQuestion I came across recently on Twitter. <br /><br />"How do I write a test when there's an Environment.Exit?! :("<br /><br />Very good question... My answer was basically rewrite the code! A really quick way to do this is create a static action that will allow you to mock it out. What if I created a class called MyEnvironment with this Action:<br /><br /><pre "code"><br /> public class MyEnvironment<br /> {<br /> public static Action<int> Exit = exitCode => Environment.Exit(exitCode);<br /> }<br /></pre><br /><br />In code I can just replace the call with this:<br /><br /><pre "code"><br /> MyEnvironment.Exit(0);<br /></pre><br /><br />And now, in my testing I can do something like this:<br /><br /><pre "code"><br /> MyEnvironment.Exit = exitCode => { };<br /></pre><br /><br />Voila! No more interrupted tests :)Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-41570970609523271402011-11-24T04:05:00.000-08:002011-11-24T05:06:38.565-08:00Dynamics CRM 2011 - unable to unregister pluginThere seems to be a bug in CRM 2011 if you make changes to a DLL or remove a DLL from the server/bin/assembly folder and subsequently try to unregister the associated plugin. For some reason (I have yet to figure out) 2011 needs to load that plugin assembly again before it can unregister it. Obviously it runs into problems trying to reload this plugin and throws an error. My best guess as to why it needs to do this is it has to unregister the SDKMessageProcessingSteps in the background and I bet that as soon as it attempts to access these items it attempts to load up the assembly. So we end up with a catch 22 situation.<br /><br />Here's a way to see this in action:<br /><br />1. Create a basic plugin called something like "TestPlugin"<br /><br />2. Copy the plugin dll to the server/bin/assembly folder<br /><br />3. Register this plugin using the "Disk" option using the PluginRegistrationTool<br /><br />4. Test the plugin (so that it is loaded and activated)<br /><br />5. Go back to the code and change the plugin name to something like "TestPluginNameChange"<br /><br />6. Copy the DLLs over again (If you get an access error on the files perform an IISReset)<br /><br />7. Try to unregister the plugin...<br /><br />You end up getting an error something like this:<br /><br /><pre "code"><br /> <ErrorCode>-2147220970</ErrorCode><br /> <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" /><br /> <Message>System.Web.HttpUnhandledException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #A28C2B17</Message><br /></pre><br /><br />So what's the solution? There's a few options here. <br /><br />1. Copy back in the old DLLs... I don't usually have the original DLLs so that's out (I'm usually in developer mode when this happens and quickly recycling DLLs). <br /><br />2. If it's an easy edit try to revert your code back and copy in these DLLs. Attempt to unregister.<br /><br />3. If this doesn't work try to update the assembly with the new DLLs (that were edited as close back to the originals as possible). Then unregister.<br /><br />4. If this still fails try to update the assembly again but this time switch over from Disk to Database. Then unregister.<br /><br />5. If you're reading this step you've managed to create a situation I once ran into as well... and couldn't resolve... watch this space for a solution!<br /><br /><br />All in all, be careful with plugins during development. When replacing a plugin that you've edited quite a lot try get into a habit of unloading the existing assemblies before you load up the new ones. Just takes one slip and you land yourself in a bit of a mess.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-28008433256132890652011-10-25T09:39:00.001-07:002011-10-25T09:42:36.842-07:00Silverlight, JSON and dynamic types...Todays Dynamics 2011 task was to investigate using JSON within a Silverlight control. I started this task with high levels of excitement being new to the whole restful/JSON scene. Yes, I know, I am a bit of a late-comer here! The purpose of this task was to create a generic control I could put on a Dynamics CRM Form. This control was going to be driven by data from an external restful service. I don't want to have to reconfigure this control every time my data changes, so the purpose is to drive the label and value from this external source. So, this isn't about communicating with a Dynamics database using OData/JSON. <br /><br />A quick google on how I do this results in me writing the following snippet:<br /><br /><pre "code"><span style="font-family:courier new;font-size:85%;"><br /> var proxy = new WebClient();<br /> proxy.OpenReadCompleted += proxy_OpenReadCompleted;<br /> proxy.OpenReadAsync(new Uri("restfulurl"));<br /><br /> // Calling the following method...<br /> private void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)<br /> {<br /> var strm = new StreamReader(e.Result);<br /> string jsonText = strm.ReadToEnd();<br /> // ... etc<br /> }</span><br /></pre><br /><br />This is where I hit my first road block: Cross site scripting. I spent quite a while on that, and still haven't figured out what I'm going to do, so I'm going to save that for another post. Plus, this really boils down to a Dynamics 2011 cloud issue, so let's move on. If you're not doing this via Dynamics 2011 then you should be able to do the above in a standard Silverlight control. For now I shall spoof the JSON by hardcoding the string...<br /><br />Next, how do we parse this into a dynamic type? In C# 4.0 we can do some really nice stuff like this:<br /><br /><pre "code"><span style="font-family:courier new;font-size:85%;"><br />using System.Web.Script.Serialization;<br /><br />...<br /><br />JavaScriptSerializer jss = new JavaScriptSerializer();<br />var d = jss.Deserialize<dynamic>(jsonText);</span><br /></pre><br /><br />Roadblock 2... JavaScriptSerializer was depreciated after Silverlight 1.1... HRMPH!<br /><br />Silverlight, sometimes I hate you...<br /><br />After countless searches and getting very close to embarking on a journey to build a JSON parser... I'm going to give a call out to a great <a href="http://procbits.com/2011/08/11/fridaythe13th-the-best-json-parser-for-silverlight-and-net">blog post by jprichardson here</a>. Saved me a few days effort, cheers mate! I quickly grabbed this source from GIT, built it, and stuck the silverlight libraries into my project. Now I do this:<br /><br /><pre "code"><span style="font-family:courier new;font-size:85%;"><br /> var jsp = new JsonParser();<br /> dynamic json = jsp.Parse(jsonText);</span><br /></pre><br /><br /><br />Whazzam, I have dynamic object from my JSON!<br /><br />I have to say though, the deeper I dig into Silverlight the more shocked I am at the little things that take so much effort...Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-37255723084733284652011-09-27T02:30:00.000-07:002011-09-27T02:49:54.854-07:00How to post code in blogger... part deux!Ok, after struggling initially with posting code in blogger (<a href="http://karmagarda.blogspot.com/2009/08/posting-html-code-in-blogger.html">posting html code in blogger</a>) I managed to figure out a much better way to do this. At the time of posting the above I didn't realise the following tags existed:<br /><br /><pre name="code"><br /><pre name="code"><br /> code goes here!<br /></pre><br /></pre><br /><br />This is much better and results in better formatted posts. The only real "gotcha" is you'll have to replace some "html" style tags with their html safe equivalent. For example, "<" becomes "&lt;"<br /><br />Now to go back and fix my blog...Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-61837937006799683322011-09-19T06:15:00.000-07:002011-10-31T05:52:07.553-07:00MS Dynamics 2011 and MVVMSo, I've been out of the Microsoft Dynamics world for about a year now (and semi AWOL in the process!), but after changing jobs I find myself back in this world using 2011. First up, Silverlight! Now, I have have started to notice quite a bit that a lot of samples or guides on CRM 2011 and Silverlight don't seem to use MVVM. Why on earth is that? First things first, this in my opinion sheds a very bad light on Dynamics development. The very first project I get to work on had already been started by a previous developer. I open up the project and to my dismay I see absolutely zero view models. Task 1 - Push TDD.<br /><br />So, why would we not use MVVM in Dynamics 2011? Let's walk through a sample I found and my phase 1 of refactoring. I open up the code behind and find this:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> private DataItemCollection _collection;<br /> public System.String _serverUrl;<br /> private string _userId;<br /> public MainPage()<br /> {<br /> InitializeComponent();<br /> this.Loaded += new RoutedEventHandler(MainPage_Loaded);<br /> }<br /><br /> void MainPage_Loaded(object sender, RoutedEventArgs e)<br /> {<br /> GetPageInformation();<br /> LoadCompanies();<br /> }<br /><br /> private void LoadCompanies()<br /> {<br /> _collection = new DataItemCollection();<br /> QueryExpression query = QueriesHelper.GetAllAccounts();<br /> SoapHelper.BeginExecuteRetrieveMultiple(query, new AsyncCallback(GetAccountsCompleted), null);<br /> }<br /><br /> private void GetAccountsCompleted(IAsyncResult result)<br /> {<br /> OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);<br /> if ((response != null) && (response.Results.Count > 0))<br /> {<br /><br /><em>...I SHALL PROTECT YOUR EYES FROM A MONSTROSITY OF A FUNCTION HERE...</em><br /><br /> }<br /><br /> if (!Deployment.Current.Dispatcher.CheckAccess())<br /> {<br /> Deployment.Current.Dispatcher.BeginInvoke(delegate()<br /> {<br /> this.TreeViewClients.DataContext = _collection;<br /> });<br /> }<br /> else<br /> {<br /> this.TreeViewClients.DataContext = _collection;<br /> } <br /> }<br /><br /> private void GetPageInformation()<br /> {<br /> ScriptObject xrm = (ScriptObject)HtmlPage.Window.GetProperty("Xrm");<br /> ScriptObject page = (ScriptObject)xrm.GetProperty("Page");<br /> ScriptObject pageContext = (ScriptObject)page.GetProperty("context");<br /> _userId = (string)pageContext.Invoke("getUserId");<br /> _serverUrl = (string)pageContext.Invoke("getServerUrl");<br /> }<br /></span></pre><br /><br />So what do we have here? What hints do I get as to why we wouldn't implement MVVM? Ok, so it looks like either the developer hadn't done much Silverlight/WPF before... or didn't quite know how to MVVM this. Looking at the code I can see that there's 2 things that we need to be considerate of when considering MVVM:<br /><br />1. Queries need to run Asynchronous.<br /><br />2. Access to our dispatcher for when we need to run "stuff" on the UI thread.<br /><br />So how do we move this across to a MVVM structure then? Step 1, let's create a ViewModel:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> public class MyDamnViewModel<br /> {<br /> private readonly Dispatcher _dispatcher;<br /><br /> public TeamCalendarViewModel()<br /> {<br /> _dispatcher = Deployment.Current.Dispatcher;<br /> }<br /> }<br /></span></pre><br /><br />One plan here will be to allow for testing, but for now just copy the dispatcher to a local variable.<br /><br />So what else can we add to this? How about everything! Considering the old form set everything up in the "onload" let's go with this for now. Let's just copy ALL methods across to my viewmodel and add the 2 method calls to our ViewModel constructor (GetPageInformation and LoadCompanies)... This will cause 1 major problem...<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> this.TreeViewClients.DataContext = _collection;<br /></span></pre><br /><br />What do we do? I notice my DataItemCollection already inherits from ObservableCollection... let's work with that for now and mark for review... Refactor the variable _collection so that we expose as a public ObservableCollection property:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> private DataItemCollection _collection; <br /> public ObservableCollection<DataItem> NowWeHaveACollection <br /> { <br /> get { return _collection; } <br /> set <br /> { <br /> _collection= (DataItemCollection)value; <br /> NotifyPropertyChanged("NowWeHaveACollection"); <br /> } <br /> } <br /></span></pre><br /><br />I won't go into NotifyPropertyChanged stuff into too much depth here... but to get us by I just inherited from INotifyPropertyChanged and added this code to the view model:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> public event PropertyChangedEventHandler PropertyChanged;<br /> protected void NotifyPropertyChanged(String info)<br /> {<br /> if (PropertyChanged != null)<br /> {<br /> PropertyChanged(this, new PropertyChangedEventArgs(info));<br /> }<br /> }<br /></span></pre><br /><br />Let's worry about refactoring and tidying all that up in a phase 2. For now I just want to get a basic MVVM structure in place.<br /><br />So what did this new property give us? We can just set the property instead of directly accessing the control:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> NowWeHaveACollection = _collection;<br /></span></pre><br /><br />Nearly there yet boss? Not quite. Code should be there, but we don't have anything hooked up. Let's set up our datacontext in the XAML:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> <usercontrol.datacontext> <br /> <MyDamnViewModel /> <br /> </usercontrol.datacontext><br /></span></pre><br /><br />And set our bindings up in the XAML instead of in the code. In my case it was a telerik tree view so we have converters and all sorts of rubbish in the code... I'll save that for another post. Let's pretend for now it's a bog standard list or something. Set this on your object in the XAML:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> ItemsSource="{Binding NowWeHaveACollection}"<br /></span></pre><br /><br />And now our main form looks like this:<br /><br /><pre name="code"><span style="font-family:courier new;font-size:85%;"><br /> public partial class MainPage : UserControl<br /> {<br /> public MainPage()<br /> {<br /> InitializeComponent();<br /> }<br /> }<br /></span></pre><br /><br />Ignoring the fact that it's called "MainPage" and some "phase 2" refactoring we're pretty much done. <br /><br />So, to answer the question - No reason not to use MVVM in Dynamics 2011. I'd like to see less samples using direct code behind please!!Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-61482031377694169312010-09-01T01:18:00.001-07:002010-09-01T01:18:39.850-07:00How do you copy the text from a standard windows message box?Press CTRL+C<br /><br />Easiest tip EVER!Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-47531322274976804542010-05-10T04:23:00.000-07:002010-09-01T01:24:07.908-07:00How to create an email validator on a web pageCame across this requirement recently on an asp.net application I'm developing. Handy to know that you can easily create a regular expression to handle email formats like this:<br /><br /><asp:textbox id="textbox1" runat="server"/><br /><asp:RegularExpressionValidator id="valRegEx" runat="server"<br /> ControlToValidate="textbox1"<br /> ValidationExpression=".*@.*\..*"<br /> ErrorMessage="* Your entry is not a valid e-mail address."<br /> display="dynamic">*<br /></asp:RegularExpressionValidator>Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-50116617063946108652009-11-13T05:59:00.000-08:002009-11-13T06:01:49.779-08:00SQL Server - How do I select just the date portion of a datetime fieldThere are a few ways to do this, but I find the easiest is to use the float version of a datetime and crop off the decimal portion (right of the decimal place is the time portion)<br /><br />DECLARE @currentDate DateTime<br />SET @currentDate = Cast(Floor(Cast(GetDate() as Float )) As DateTime)Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-51400050393751699922009-10-09T02:39:00.000-07:002009-10-18T09:53:10.238-07:00"Failed to pause full-text catalog for backup" while backing up a databaseSo you're trying to back up your database and you get the following error:<br /><br /><blockquote>Failed to pause full-text catalog for backup. Backup was aborted. Check to make sure Microsoft Full-text Service is running properly and SQL server service have access to full-text service.</blockquote><br /><br />There are a couple of things that could be up here. Try all of the following and see if that get's you out of this:<br /><br />1. Check if the full text service is running. This can be found by opening up the windows services and locating either "SQL Server Full Text Search" or "Microsoft Search Service". If it's not running or disabled then this may be your problem- Retry the backup.<br /><br />2. Ensure full text catalog is enabled on the databases by running the following command:<br /><br />exec sp_fulltext_database 'enable'<br /><br />Retry the backup.<br /><br />3. If all of the above fails take a note of how the full text catalog is set up on the database in question. It should be accessible via Storage -> Full Text Catalogs. When you see what tables and fields it references try dropping and recreating the full text catalog. Retry the backup.<br /><br /><br />Hope this helps!<br /><br /><a href="http://www.blogged.com/blogs/karma-gardas-snippets-diary.html"><br /><img src="http://www.blogged.com/icons/vn_karmag_1513816.gif" border="0" alt="Karma Gardas Snippets Diary - Blogged" title="Karma Gardas Snippets Diary - Blogged" /></a>Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-23816151919174662372009-10-09T01:32:00.000-07:002009-10-09T01:46:56.426-07:00"The virtual directory specified already exists"... but it doesn't!I've come across this issue intermittently on some servers, but I haven't figured out yet why it happens. The times I've seen it happen is when the virtual folder wasn't created with all the permissions required, and then deleting it seems to leave a remnants of it behind. An example of this is when you cannot locate the virtual directory but can see it referenced by an app pool.<br /><br />So, how do you get rid of it?<br /><br />9 times out of 10 the following works for me. Let's say the new virtual directory is called "MyDir" and was located in the web site "My Web"<br /><br />- Open up a command prompt<br />- Type in the following command:<br /><br />IIsVDir /delete "My Web"/MyDir<br /><br />Sometimes if that doesn't work creating the virtual directory (using the same name - MyDir in this example) and running the above command again usually works.<br /><br />If anyone can shed any light on why this remnants happens please do.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-8929685302722522002009-10-02T05:07:00.000-07:002009-10-02T05:09:35.678-07:00How to programatically move the mouse in C#.Net gives you access the mouse via "Cursor". You can interact with the mouse position like this:<br /><br /><br />Cursor.Position = new Point(Cursor.Position.X + 10, Cursor.Position.Y + 10);<br /><br />Easy peesyKarma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-26534243523689732432009-09-29T06:01:00.000-07:002009-09-29T07:19:09.600-07:00DateTime.Min != SqlDateTime.MinYes, as the title says, .Net DateTime Minimum does not equal Sql Servers equivalent. For whatever reason you come across this gem of an issue you have a couple of options to get around it. <br /><br />1. Use a .net Nullable datetime instead. i.e. Declare your "DateTime" as "DateTime?". Putting question marks after a lot of .Net variable types in C# turns them into nullable types.<br /><br />2. If you really do need the min date, use SqlDateTime.Min.Value. "Value" gives you access to a DateTime type containing SQLs min date.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-56678715467131940012009-08-26T06:34:00.000-07:002009-08-26T09:47:24.554-07:00SQL Server - Select rows of a "max date" from a table (using ROW_NUMBER() OVER)I often come across different requirements where I need to get the "top row" where certain criteria exists. It often applies to VAT Rates, Exchange Rates, even historical data where a different record may apply depending on the scenario. For this example, let's use VAT rates.<br /><br />Let's create sample data using the following:<br /><br />create table #myvattable (vatname nvarchar(50), effectivedate datetime)<br />insert #myvattable values('Rate A', '01/01/2009')<br />insert #myvattable values('Rate B', '01/01/2009')<br />insert #myvattable values('Rate C', '01/01/2009')<br />insert #myvattable values('Rate A', '01/02/2009')<br />insert #myvattable values('Rate B', '01/02/2009')<br />insert #myvattable values('Rate B', '01/02/2008')<br /><br /><br />So, we have several instances of the same "Rate" in the table that have different effective dates. Now, let's take this requirement:<br /><br />I want to retrieve all VAT rates applicable for a certain date. How do we do this?<br /><br /><br /><strong>Step 1 - use a row_number() clause on your dataset:</strong><br /><br />select * from<br />(<br />select row_number() over (partition by a.vatname order by a.vatname, a.effectivedate desc) as rownum,<br />a.vatname, a.effectivedate<br />from #myvattable a<br />)<br />tbl<br /><br /><br /><br />This simply puts a row_number clause on each row partitioning by the vatname. This returns a result set similar to this:<br /><br />rownum vatname effectivedate<br />------ ------------- -----------------------<br />1 Rate A 2009-01-02 00:00:00.000<br />2 Rate A 2009-01-01 00:00:00.000<br />1 Rate B 2009-01-02 00:00:00.000<br />2 Rate B 2009-01-01 00:00:00.000<br />3 Rate B 2008-01-02 00:00:00.000<br />1 Rate C 2009-01-01 00:00:00.000<br /><br /><br />Ok, so what does this do for us? It effectively ranks the rows by each vatname so that we can see which ones are most applicable. Basically we want all the 1's. <br /><br /><strong>Step 2 - Filter the rownums. </strong><br />So our query becomes this:<br /><br />select * from<br />(<br />select row_number() over (partition by a.vatname order by a.vatname, a.effectivedate desc) as rownum,<br />a.vatname, a.effectivedate<br />from #myvattable a<br />)<br />tbl<br />where rownum = 1<br /><br /><br />Ok, pretty much there now. The only step really that is left is... what if someone wants historical data? This query is fixed to the latest most applicable vatrate. <br /><br /><br /><strong>Step 3 - Make the date flexible</strong><br /><br />select * from<br />(<br />select row_number() over (partition by a.vatname order by a.vatname, a.effectivedate desc) as rownum,<br />a.vatname, a.effectivedate<br />from #myvattable a<br />where effectivedate <= @DATEVARIABLE )<br />tbl<br />where rownum = 1<br /><br /><br />So, @DATEVARIABLE could be a parameter/variable... or, even better, a field from another joined table.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-69240646932728252482009-08-25T07:14:00.000-07:002009-08-25T08:59:33.429-07:00How to calculate the width/height of a string in a particular font- Follow up from the listbox width issue -<br /><br />This applies to mainly asp.net, but the technique for winforms isn't drastically different. What we need to use is a Graphics object to measure a string width. Here's how:<br /><br /><br />// Bitmap is solely required for creating the graphics object<br />Bitmap TextBitmap = new Bitmap(1, 1);<br />Graphics g = Graphics.FromImage(TextBitmap);<br /><br />// Create the font relative to the text (let's say Arial 8)<br />Font myFont = new Font("Arial", 8);<br />SizeF fontSize = g.MeasureString("This is a test string", myFont);<br /><br /><br /><br />Done. The values you need are fontSize.Height and fontSize.Width.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-41124927937557572332009-08-25T04:24:00.000-07:002011-10-25T09:53:54.977-07:00Add horizontal scroll ability to asp.net listbox controlFirstly, an asp.net listbox control doesn't give you horizontal scrollbars (booo!). Depending on your requirements, there is a fairly easy way to achieve this without writing a custom control. <br /><br />Step 1, wrap your listbox in a div:<br /><br /><div id='hello' style="OVERFLOW: auto; width: 200px; height: 200px;"> <br /><asp:ListBox Rows="6" Width="200px" ID="lstAvailable" runat="server" DataValueField="UserId" SelectionMode="Multiple" Height="200px"> <br /></asp:ListBox> <br /></div> <br /><br /><br />Step 2. Because this doesn't completely solve the problem (The listbox is a fixed size so it will still disply scrollbars) on page load let's calculate the size we need the listbox to be. The we can fit all rows at the correct width. Use this function:<br /><br /><br />private void ResizeListboxes()<br />{<br /> // Bitmap is solely required for creating the graphics object<br /> Bitmap TextBitmap = new Bitmap(1, 1);<br /> Graphics g = Graphics.FromImage(TextBitmap);<br /><br /> // Create the font size relative to the list box<br /> Font listFont = new System.Drawing.Font(lstAvailable.Font.Name, 8);<br /> SizeF fontSize = new SizeF(200, listFont.Height);<br /><br /> // Loop through the list and find the widest string taking font type into consideration<br /> foreach (ListItem li in lstAvailable.Items)<br /> {<br /> SizeF currentFontSize = g.MeasureString(li.Text, listFont);<br /> if (currentFontSize.Width > fontSize.Width)<br /> fontSize = new SizeF(currentFontSize);<br /> }<br /><br /> // Calculate the required height and width of the list box, min of 200 for each<br /> Int32 calculatedHeight = Convert.ToInt32(lstAvailable.Items.Count * fontSize.Height);<br /> Int32 calculatedWidth = Convert.ToInt32(fontSize.Width);<br /> lstAvailable.Width = (calculatedWidth < 200 ? 200 : calculatedWidth);<br /> lstAvailable.Height = (calculatedHeight < 200 ? 200 : calculatedHeight);<br /><br />}<br /><br />Call this on page load and you should be done.<br /><br />Note: I hardcoded a fontsize of 8. I'm sure you could have gotten this from the listbox too.<br /><br />Also, some people are not fond of this solution (including me!). I may post a custom control version too at a later stage.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-76694512857069910622009-08-25T04:23:00.000-07:002009-08-25T07:30:24.385-07:00How to create a System.Drawing.Graphics object in Asp.NetQuick and easy way to do this is create a bitmap and use that:<br /><br />Bitmap TextBitmap = new Bitmap(1, 1);<br />Graphics g = Graphics.FromImage(TextBitmap);Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-55287980208780349992009-08-21T03:06:00.000-07:002009-08-21T07:27:09.216-07:00How to close a window using ASP.Net server sideAfter doing what needs to be done you can register some startup script to close your browser window like this:<br /><br />string closeScript = "<script language="javascript">window.top.close();</script>";<br />if (!ClientScript.IsStartupScriptRegistered("clientScript"))<br /> ClientScript.RegisterStartupScript(Page.GetType(), "clientScript", closeScript);Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-17761949149264453372009-08-20T09:45:00.001-07:002010-09-01T01:22:32.023-07:00Getting the dialog arguments passed into a web page modal dialogThis is especially useful if you use Microsoft CRM. Because it ties in very closely to how the entity forms and grid views communicate to custom web pages etc.<br /><br />For example, in Microsoft CRM you can edit the ISVConfig to add a button to the toolbar for the entity grid. Set the WinMode=2 (2 basically means a modal dialog) to allow CRM to provide you with the selected entities. So how do we know what items were selected in the entity list? It passes us in a list of IDs as part of the window.dialogArguments.<br /><br />So, how do we get access to this? Through javascript. Here's the steps:<br /><br />1. Create the following javascript function (available from MSCRM help pages):<br /><br />function loadSelectedListItems() {<br /> var sGUIDValues = "";<br /> var selectedValues;<br /> //Make sure window.dialogArguments is available.<br /> if (window.dialogArguments) {<br /> selectedValues = new Array(window.dialogArguments.length - 1);<br /> }<br /> else {<br /> return<br /> }<br /> selectedValues = window.dialogArguments;<br /> if (selectedValues != null) {<br /> for (i = 0; i < selectedValues.length; i++) {<br /> sGUIDValues += selectedValues[i] + ",";<br /> }<br /> document.getElementById('<%= winDialogArguments.ClientID %>').value = sGUIDValues;<br /> }<br />}<br /><br /><br />2. Use this function as part of the onload of the body:<br /><body onload="loadSelectedListItems()"> <br /><br />3. Create a new holder object (in my example an asp textbox) in a hidden division on your form: <br /><div style="visibility: hidden"><br />         <asp:textbox id="winDialogArguments" runat="server" text=""><br /></div><br /><br /><br /><br />Job done. Just access the Text of the asp textbox server side on the next post back (e.g. click of an OK button) to get the list of IDs.Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com2tag:blogger.com,1999:blog-7832782012725042549.post-34799458439038084992009-08-20T05:08:00.000-07:002009-08-20T08:55:20.624-07:00Web Page Modal Dialog opens new window on postbackIf you have a web page that's opening as a Modal Dialog (using window.showModalDialog or similar) and you are finding your button post backs are opening up a new browser window... here's the code that generally stops it happening. At the top of your head tag insert the following:<br /><br />    <base target="_self" /><br /><br />In some instances this won't work. If not then pop this onload script in the body:<br /><br /><body onLoad="window.name='myDialogWindow' ......> <br /><br /><br />and set the base tag to this instead:<br /><br />    <base target="myDialogWindow" />Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-91267517647109383192009-08-20T04:37:00.000-07:002011-09-27T02:51:30.700-07:00Posting html code in Blogger(Read my <a href="http://karmagarda.blogspot.com/2011/09/how-to-post-code-in-blogger-part-deux.html">newer post here</a> before using this method...)<br /><br />Funny, on my very first post in Blogger I struggled getting the code to display. Want a real easy, non fancy way of getting it to display? Convert your html to html safe code. Here's a really nice site for this:<br /><br /><a href="http://www.htmlconvert.net/">http://www.htmlconvert.net/</a><br /><br />If you want all tags converted then ensure to select the "Convert Tags" or "Convert and Colourize Tags" option.<br /><br />Edit: Have noticed the above link is not working anymore... will post an update when I find another nice site :)Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0tag:blogger.com,1999:blog-7832782012725042549.post-56283825371270695382009-08-20T04:22:00.000-07:002009-08-21T05:48:32.386-07:00How to close a window with an asp button (ASP.Net) using JavascriptA really handy way to do this:<br /><br /><a href="#" onClick="javascript:window.close();"><br />     <asp:Button ID="btnCancel" Text="Cancel" runat="server" /><br /></a>Karma Gardahttp://www.blogger.com/profile/13194388501931523076noreply@blogger.com0