Thursday, August 7, 2014

C# finding duplicates in a List using LINQ



Suppose you have a list that contains entries repeated more than once.
Using LINQ you can get the repeated elements and their values.

The easiest way to solve the problem is to group the elements based on their value, and then pick a rapresentative of the gorup if the elements in it are more than 1.
In linq, this translates to:
    var query = lst.GroupBy(x=>x)

              .Where(g=>g.Count()>1)

              .Select(y=>y.Key)

              .ToList();

You can replace x=>x with x => x.Property if your list is a list of complex objects and you want to search for a specific duplicate value. If you compare objects you need to override equals.
If you want to know how many times the elements are repeated, you can use:

    var query = lst.GroupBy(x=>x)

              .Where(g=>g.Count()>1)

              .Select(y=> new { Element = y.Key, Counter = g.Count()})

              .ToList();

Submit this story to DotNetKicks

Saturday, July 26, 2014

Slugify a tile in excel


So, this in not properly a C# article.
I needed to write a function in Excel that create a slug (or a premalink) out of a title.
Permalink is a valid url created out of a piece of text (usually a blog post title).
The operation are quite simple: all lowercase, replace spaces and non alphabet characters with -, convert accents to plain (eg à becames a).
So in excel just VBA works as standard, so I take the slugify funcion in Orchard CMS open source that is C# and I converted in VBA.
Pretty easy? No.
Anyway I did it...

The original code follows:

        private string Slugify(FillSlugContext slugContext) {
            _slugEventHandler.FillingSlugFromTitle(slugContext);

            if (!slugContext.Adjusted) {

                var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+");

                var cleanedSlug = disallowed.Replace(slugContext.Title, "-").Trim('-','.');

                slugContext.Slug = Regex.Replace(cleanedSlug, @"\-{2,}", "-");

                if (slugContext.Slug.Length > 1000)
                    slugContext.Slug = slugContext.Slug.Substring(0, 1000).Trim('-', '.');

                slugContext.Slug = StringExtensions.RemoveDiacritics(slugContext.Slug.ToLower());
            }
            
            _slugEventHandler.FilledSlugFromTitle(slugContext);

            return slugContext.Slug;
        }

And this is the VBA result...


Function CreateSlug(text As String) As String
    
    Dim cleanedSlug As String
    cleanedSlug = text
    
    'Regex that replaces any invalid char with an -
    Set regEx = New RegExp
    regEx.Pattern = "[:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+"
    regEx.IgnoreCase = True

    'The loop is needed because in vba it matches just first char in string
    Dim tm As String
    Do
        tm = cleanedSlug
        cleanedSlug = regEx.Replace(cleanedSlug, "-")
    Loop While (tm <> cleanedSlug)
    
    'removes all trailing - left    
    cleanedSlug = Trim(cleanedSlug, "-")

    'if there are 2 - replace with 1    
    regEx.Pattern = "\-{2,}"
    cleanedSlug = regEx.Replace(cleanedSlug, "-")

    'all lowercase
    cleanedSlug = LCase(cleanedSlug)

    'remove accents
    cleanedSlug = ReplaceAccents(cleanedSlug)

    'but why Vba designers removed the return keyword?
    CreateSlug = cleanedSlug
    
    Set regEx = Nothing
End Function
This helper function mimics the trim specific characters on the end of a string that does not exists in vba
Function Trim(text As String, trailing As String)

    If (Right(text, Len(trailing)) = trailing) Then
        Trim = Left(text, Len(text) - Len(trailing))
    Else
        Trim = text
    End If

End Function
This helper function remove specific accents in a string replacing with normal cheracters
Function ReplaceAccents(text As String)
    Const AccChars As String = "àáâãäåçèéêëìíîïðñòóôõöùúûüýÿø"
    Const RegChars As String = "aaaaaaceeeeiiiidnooooouuuuyyo"

    For J = 1 To Len(AccChars)
        text = Replace(text, Mid(AccChars, J, 1), Mid(RegChars, J, 1), compare:=vbBinaryCompare)
    Next J

    ReplaceAccents = text
End Function

Submit this story to DotNetKicks

Friday, February 14, 2014

The specified solution configuration “Debug|BNB” is invalid

Problem

When you try to build from command prompt or batch file you get the error

‘The specified solution configuration “Debug|BNB” is invalid. Please specify a valid solution configuration using the Configuration and Platform properties (e.g. MSBuild.exe Solution.sln /p:Configuration=Debug /p:Platform=”Any CPU”) or leave those properties blank to use the default solution configuration.

Background

You have an HP computer.
A system wide setting of an environment variable called "Platform" seems to override any other setting.

The issue

At build-time the compiler has to know what the target platform of your code, i.e. the system architecture like X86, 64bit etc. To do so it searches to "Platform" variable first, that is wrong in our case since BNB is not a valid platform for msbuild.

The solution

Delete the conflicting environment variable "Platform" in "Control Panel -- System -- Advanced -- Environment Variables". Restart your computer and try again.

Submit this story to DotNetKicks

Thursday, January 30, 2014

Encapsulate a string to act as an array of strings


Here is a quick snippet for expose in a class a string that contains values comma-separated (eg: value1,value2,value3) as an array.

    string myString;

    public string[] MyArray
    {
      get
      {
        if (string.IsNullOrEmpty(myString))
          return new string[0];
        return myString.Split(',');
      }

      set
      {
        myString = String.Join(",", value);
      }
    }

Sample input

 myString = "value1,value2,value3";

Result

myArray = string[]{ "value1", "value2", "value3" };

Tips

Be sure that string does not contains extra ',' in order to avoid unwanted splitting.

Submit this story to DotNetKicks

Asp Net config, automatically disable debug on production servers using a nice feature on machine.config

Developing in hurry is not the best thing to do but we all have to.
One of the things that I usually forgot to change in production is turning off the debug mode on web.config
So i forget to change:
<compilation debug ="true">
to
<compilation debug ="false">

So why leaving debug to true is so bad?
  • Compilation takes longer as batch optimizations are disabled 
  • Scripts and images from WebResources.axd will not be cached on the client 
  • Larger memory footprint 
  • Code will execute slower because of enabled debug paths
And you have to multiply for each site you are deplyoing in the same server.
This means wasting more memory, and having sites running much slower.
And you often cannot check every single web.config to see if the settings are right.

When deploying ASP.NET applications to a production environment, to force debug = false in all ASP.NET applications on the server, you can change the retail switch in machine.config:

<configuration>
    <system.web>
        <deployment retail="true" />
    </system.web>
</configuration>

This will also disable page output trace and force custom error pages.
This can be great generally, but can turn in a nightmare if you have a site that does not run properly since you have custom errors always on.
Solutions can be:
  • look at event log of server
  • install an aspnet logger like elmah
  • try debug locally
  • set retail to false for a while (not recommended because causes rebuild of all sites)
Have a nice day folks!

Submit this story to DotNetKicks

Monday, January 27, 2014

Using a Dictionary as the DataSource for a DropDownList

It is possible to use a Dictionary or even Dictionary<string> as the DataSource for a DropDownList directly, without having to iterate through the the Dictionary's KeyValuePair collection and populate the DropDownList's Items collection manually.

The text member is "value" and the value member is "key" when using one of these types of objects to bind to a DropdownList.

Dictionary<byte> dicTable = new Dictionary<byte>();
dicTable.Add(1, "One");
dicTable.Add(2, "Two");
dicTable.Add(3, "Three");
dicTable.Add(4, "Four");
cmbDropDownList.DataSource = dicTable;
cmbDropDownList.DataTextField = "Value";
cmbDropDownList.DataValueField = "Key";
cmbDropDownList.DataBind();

Submit this story to DotNetKicks

Friday, January 27, 2012

C# getting file names without extensions


When you walk a directory getting file names you get a file name with its extension: file1.txt, file2.txt, file3.txt.
How can you get file names without file extensions file1, file2, file3?

DirectoryInfo d = new DirectoryInfo(myDirectory);
FileInfo[] fileArrray = d.GetFiles("*.txt");
foreach (FileInfo f in smFiles)
{
   var fileNameOnly = Path.GetFileNameWithoutExtension(f.Name);
   
   //...
   //process file...
}

Thre is also a linq way:

var filenames = String.Join(", ", Directory.GetFiles(@"c:\", "*.txt")
.Select(filename => Path.GetFileNameWithoutExtension(filename)).ToArray());

Submit this story to DotNetKicks

Wednesday, January 25, 2012

Jquery tabs postback problem and solution

I am using jquery library in my project and I use jquery-ui tabs.
When a postback occurs in any tab, tabs reloaded and goes to first tab.

<script type="text/javascript">
    $(document).ready(function() {
        $("#example").tabs();
    });
</script>

Solution is to store last tab in an hidden field and reload each time page loads.

<script language="javascript" type="text/javascript">
    $(function() {
        $("#example").tabs({
            show: function() {
                var sel = $('#example').tabs('select', $("#<%= hidLastTab.ClientID %>").val(sel));

            },
            selected: <%= hidLastTab.Value %>
         });
      });
</script>
<asp:hiddenfield id="hidLastTab" runat="server" value="0"></asp:hiddenfield>

or alternatively with a funcion:

private void SelectTab(int tabNumber) {
            var script = string.Format(@"$(document).ready( function(){{ $('.tabs').tabs( 'select', {0} ); }});", --tabNumber);
            ScriptHelper.RegisterHeadScriptBlock(typeof(System.Web.UI.Page), "TabSelector", script, true);

        }


Submit this story to DotNetKicks

Thursday, January 19, 2012

What is a Method Group?

A method group is the name for a set of methods (that might be just one).
The ToString function has many overloads - the method group would be the group consisting of all the different overloads for that function.
It is a compiler term for "I know what the method name is, but I don't know the signature"; it has no existence at runtime, where it is converted in the correct overload.
Also, if you are using LINQ, you can apparently do something like myList.Select(methodGroup).
so you can replace this code:
private static int[] ParseInt(string s)
{
    var t = ParseString(s);
    var i = t.Select(x => int.Parse(x));
    return i.ToArray();
}
with this one:
private static int[] ParseInt(string s)
{
    var t = ParseString(s);
    var i = t.Select(int.Parse);
    return i.ToArray();
}

Submit this story to DotNetKicks

Saturday, January 14, 2012

Shuffle in linq (part 2)

There are many times when we need to randomly sort a list or array.
The simplest idea is to use Random.Next().

Here is the code:
public static class ShuffleExtensions
{
    public static IEnumerable<tsource>
           RandomShuffle<tsource>(this IEnumerable<tsource> source)
    {
        var rand = new Random();
        return source.Select(t => new {
                Index = rand.Next(),
                Value = t })
            .OrderBy(p => p.Index)
            .Select(p => p.Value);
    }
}

The main problem with using Random.Next() is that it is not really random. Every number will be the first in the sequence based on the supplied seed. If you call it twice with the same seed (i.e. within one tick) you will get the same number.
The distribution of random numbers over your range will be very poor and a chi-square statistical test won't do too well either to test your set of numbers for a large number of iterations.
A better approach may be using System.Guid.NewGuid() function call. This returns a new GUID for each item in the array. Since GUID's are unique and non-repeating, this guarantees each item has a unique id. LINQ OrderBy will then sort the array by the list of GUID's returned.

Here is the code:
public static class ShuffleExtensions
{
    public static IEnumerable<tsource>
           RandomShuffle<tsource>(this IEnumerable<tsource> source)
    {
        return source.Select(t => new {
                Index = System.Guid.NewGuid(),
                Value = t })
            .OrderBy(p => p.Index)
            .Select(p => p.Value);
    }
}

You can write a simple test for verify the implementations.

Here is the code:
public static void TestRandomShuffle()
{
    // create and populate the original list with 1000 elements
    var l = new List<int>(100);
    for (var i = 0; i < 100; i++)
        l.Add(i);

    var shuffled = l.RandomShuffle().ToArray();
    for (var i = 0; i < 100; i++) 
        Debug.Write(i + ":" + shuffled[i].ToString() + ",");
}

As a final notice, remember that John von Neumann said:
Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin.
:)

Submit this story to DotNetKicks

SlashDot Blogger integration that actually works!

You can add a badge or link to your Blogger to easily allow your readers to submit it to Slashdot for consideration; and once submitted, take them to the discussion.

Full description on how SlashDot badges work is here: http://slashdot.org/faq/badges.shtml

This is the actual code that you need in your template:

<script type="text/javascript">
slashdot_title="data:post.title";
slashdot_url="data:post.url";
</script>
<script src="http://slashdot.org/slashdot-it.js" type="text/javascript"></script>

To add the tag into your post template go to the Template tab under your Blogger accounts Customization section. Select "Edit HTML" and check the "Expand Widget Templates" check box. Scan the template until you find a line that looks something like "<p><data:post.body/></p>". That is where the Blogger templating engine inserts the body of your post.
I inserted my tag to appear directly below the body of my posts but you can play around with whatever position you like by using the "Preview" button. You’ll have to save the template to apply the changes when you are satisfied.

I tested the corrected code, and it’s working great!
The only probrem here is that title seems to be ignored, no idea why.
Source is correct, for some reason it is not passed to submit url page on SlashDot.

Submit this story to DotNetKicks

Friday, January 13, 2012

Extract bindings from IIS 6 metabase (the easy way)

Xslt can be very handy, specially when you have a bunch of data in xml format and you want to extract some.
To extract all the bindings froma running iis6 server the easiest way is to:

1) Create the XSL file
Save this XSLT file as metabase.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:out="urn:microsoft-catalog:XML_Metabase_V64_0">
<xsl:output method="html" />
    <xsl:template match="/">
        <html>
        <body>
            <table border="1">
            <xsl:for-each select="//out:IIsWebServer">
                <tr>
                <td><xsl:value-of select="@ServerComment" /></td>
                <td><xsl:value-of select="@ServerBindings" /></td>
                </tr>
            </xsl:for-each>
            </table>
        </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
2) Tell metabase to use the XSL
Copy the metabase in a safe place (do not edit it in place) in the same folder where you saved metabase.xsl
Metabase usually sits on folder: C:\Windows\System32\Inetsrv
Edit the second line and add this:
<?xml-stylesheet type="text/xsl" href="metabase.xsl"?>

3) Open metabase.xml with you browser
Opening metabase now will show you all bindings in a nice table.


You may copy/paste in excel if you like.

Submit this story to DotNetKicks

Wednesday, January 11, 2012

Microsoft Resource File To COFF Object Conversion Utility has stopped working


Error: 
Visual C# Command Line Compiler has stopped working or Microsoft Resource File To COFF Object Conversion Utility has stopped working 

Have you experienced either one of the above errors?

Solution:
This is a rare error and it is usually related to corrupted files or may be caused by faulty hardware (eg. a corrupted memory chip)

Fix corrupted files
To help resolve this issue, use the System File Checker tool (SFC.exe) to determine which file is causing the issue, and then replace the file. To do this, follow these steps:
  1. Open an elevated command prompt. To do this, click Start, click All Programs, click Accessories, right-click Command Prompt, and then click Run as administrator. If you are prompted for an administrator password or for a confirmation, type the password, or click Allow.
  2. Type the following command, and then press ENTER: sfc /scannow (yes there is a space after sfc) The sfc /scannow command scans all protected system files and replaces incorrect versions with correct Microsoft versions. This scan may take sometime to finish.
Try also to clear some files and folders from %TEMP% and the error may fix.

Submit this story to DotNetKicks

Thursday, December 22, 2011

No Features Selected for Upgrade

Applies to: SQL Server 2005 Express Edition, SQL Server 2008 R2 Express Edition, Windows 64-bit.

Problem Description
I have tried many times to upgrade the current SQL Server 2005 Express Edition instance installed in my computer to SQL Server 2008 R2 Express Edition, but the upgrade process always ended with the same error.
"There are no features selected for upgrade".

Cause
I was using SQL Server 2008 R2 Express 64-bit (SQLEXPR_x64_ENU) setup program to upgrade a 32-bit instance of SQL Server 2005 Express Edition. Setup cannot upgrade from 32-bit platform to 64-bit platform: cross-platform upgrade is not supported.

Solution
I ran SQL Server 2008 R2 Express 32-bit (SQLEXPR_x86_ENU.exe) setup program and setup was able to detect the existing 32-bit instance of SQL Server 2005 Express and upgraded it successfully.

Submit this story to DotNetKicks

Wednesday, December 21, 2011

Using required field validator with dropdownlist

The requiredfieldvalidator can be used for a dropdown list, you just need to set InitialValue property of the RequiredFieldValidator with the InitialValue of the DropDownList to make it work

<asp:DropDownList ID="DropDownList1" runat="server">
    <asp:ListItem>--Select--</asp:ListItem>
    <asp:ListItem>First Item</asp:ListItem>
    <asp:ListItem>Second Item</asp:ListItem>
    <asp:ListItem>Third Item</asp:ListItem>
</asp:DropDownList>

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
      ControlToValidate="DropDownList1"
      ErrorMessage="Value Required!"
      InitialValue="--Select--">
</asp:RequiredFieldValidator>


Submit this story to DotNetKicks

Preventing your site from being indexed, the right way

The robots exclusion protocol (REP), or robots.txt is a text file webmasters create to instruct robots (typically search engine robots) on how to crawl & index pages on their website.
Some people use robots.txt files to prevent sites from being indexed and thus showing up in the search engines.
But robots.txt doesn't actually do the latter, even though it does prevent your site from being indexed.
So, if you want to effectively hide pages from the search engines, and this might seem contradictory, you need them to index those pages. Why? Because when they index those pages, you can tell them not to List them. There's two ways of doing that:

Using meta tag on every page
By using robots meta tags, like this:
<meta name="robots" content="noindex,nofollow"/>

The issue with a tag like that is that you have to add it to each and every page. That's why the search engines came up with the X-Robots-Tag HTTP header.

Setting up for a whole site using IIS
If your site is running on IIS you can do by adding a custom HTTP Header
IIS 6: right-click on the "Web Sites" folder > Properties > HTTP Headers
IIS 7: on the server home screen, click on HTTP Request Headers, choose "add"
Name: X-Robots-Tag
Value: noindex, nofollow
And it'd have the effect that that entire site can be indexed, but will never be shown in the search results.
So, get rid of that robots.txt file with Disallow: / in it, and use the X-Robots-Tag instead!

Submit this story to DotNetKicks

Monday, December 19, 2011

Convert MySQL to MS Sql Server

Recently I needed to convert some MySQL tables to MS Sql Server.
It’s not too hard convert them by hand, but it is oh so tedious…
Gath Adams proved to have a quick and simple solution for this: cut the mysql table, paste into his blog and press convert.
http://gathadams.com/2008/02/07/convert-mysql-to-ms-sql-server/

Submit this story to DotNetKicks

Friday, December 16, 2011

Redirecting Assembly Versions

When you build a .NET Framework application against a specific version of a strong-named assembly, the application uses that version of the assembly at run time. However, sometimes you might want the application to run against a newer version of an assembly. An application configuration file, machine configuration file, or a publisher policy file can redirect one version of an assembly to another.
The simplest, is to modify the assembly bindings to redirect one version of an assembly to another.
In the example below the bindingRedirect allows requests for version 1.0.0.0 of this particular assembly to be serviced by version 2.0.0.0. So long as we’re sure the deserializing functionality is compatible, this solves the problem without having to change any code.

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 <dependentAssembly>
 <assemblyIdentity name="Configuration" publicKeyToken="........." culture=""/>
 <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
 <codeBase href="C:\bin\Configuration.dll" version="2.0.0.0" />
 </dependentAssembly>
</assemblyBinding>

Submit this story to DotNetKicks

Thursday, December 15, 2011

Shuffle in Linq (Part 1)

A simple implementation for shuffling a list in linq.
public static class ShuffleExtensions
{
    public static IEnumerable<tsource> 
           RandomShuffle<tsource>(this IEnumerable<tsource> source)
    {
        var rand = new Random();
        return source.Select(t => new { 
                Index = rand.Next(), 
                Value = t })
            .OrderBy(p => p.Index)
            .Select(p => p.Value);
    }
}

Submit this story to DotNetKicks

How to programmatically set DataPager PageSize

DataPager1.PageSize = xx

Where xx is the size (Integer), you could put it in the Page_Init or Page_Load event, before any DataBind.
If your DataPager is within the ListView you'd have to find it first, and you could do that using the FindControl method.
If the DataPager is outside the Listview obviously, you don't have to find it using the FindControl method.
Also, If you're not using a data source (like the SqlDataSource) you would also provide the .DataSource property before you execute .DataBind on your Listview.

Submit this story to DotNetKicks