venerdì 14 ottobre 2011 #

The maximum message size quota for incoming messages (65535) has been exceeded

exception_quota

This exception is thrown by a WCF web service published on IIS if you try to download by soap a serialized object (an image for instance) which in  Base64 is longer than 216-1 bytes.

To avoid the exception you need to change the Client Application configuration, not the server configuration. In my case it is a windows forms application built to test the service so I have to change the app.config, while in a web application I would have to change the web.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>

        <binding name="BasicHttpBinding_ISoapWS" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65535" maxBufferPoolSize="500000" maxReceivedMessageSize="65535"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="64" maxStringContentLength="65535" maxArrayLength="65535"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>

      </basicHttpBinding>
    </bindings>
    <client>

      <endpoint address="http://localhost/MyWebservice/ServiceClass.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISoapWS"
        contract="SoapWsTest.ISoapWS" name="BasicHttpBinding_ISoapWS" />

    </client>
  </system.serviceModel>
</configuration>

On the above configuration you need to change the following attributes

  • maxBufferSize="65535"
  • maxBufferPoolSize="500000"
  • maxReceivedMessageSize="65535"
  • maxStringContentLength="65535"
  • maxArrayLength="65535"

To a value you think is large enough for your needs. Pay attention if you don’t change them all, you will receive a further exception for each parameter not large enough. The value depends on you so if you need to read images or PDF files you can raise the values above the millions, because Base64 is one of the less optimized data exchange formats.

posted @ venerdì 14 ottobre 2011 22.12 | Feedback (0)

Wonderful Conversions

Yesterday I’ve blogged a memo showing some unusual conversions due to a Checksum routine I wrote for Alberto. Today I discovered that the real checksum was a little more cumbersome than I thought so I publish a few more conversions I made, just to help who will have the “luck” to bang on this kind of things.

Get a sub-array of a byte array

byte[] sourceArray;
... //Initialization with a file read or a serial port read
byte[] destArray = new byte[desiredSublength]
Array.Copy(sourceArray, StartIndex, destArray, DestStartIndex, Length);

Conversion of the bytes in correspondant ascii chars

char[] chars = System.Text.Encoding.UTF8.GetChars(destArray);

Get a string from a portion of the characters array

string subValue = new string(charsArray, startIndex, length);

Convert a string representing an hex number into a byte

byte myHexByte = Convert.ToByte("1C", 16);

Convert a byte into an HexNumber String

string hexString = Convert.ToString(myByteValue, 16);

Be sure the string has the correct Case

string lowerHex = hexString.ToLower();
string upperHex = hexString.ToUpper();

That’s because db and DB are the same as a numeric value, but become different if you convert the string to a char array

char[] hexLetters = upperHex.ToCharArray();

And then you convert the char array back to a byte array

byte[] bytesFromHexLetters = new byte[hexLetters.Length];
for (int i = 0; i < hexLetters.Length; i++)
{
   bytesFromHexLetters [i] = Convert.ToByte(chars[i]);
}

Try it with upper and lower case hex letters and you’ll see. And all this in a single checksum check routine Con la lingua fuori here we call this kind of things Simple Business Complication Office (sometimes it is a very crowded office).

posted @ venerdì 14 ottobre 2011 21.23 | Feedback (0)

mercoledì 12 ottobre 2011 #

Convert a byte[] in an int16[] and convert a number in a binary string

Two things you surely don’t do every day, especially if like me you work with database and user interfaces, but today Alberto asked me a little help with a byte array and a strange checksum and to be able to make the verifications manually I had to use both things in this subject. So I blog a note to know where to find them next time.

 

Convert a byte[] in a short[] (o int16[]) but it would be the same with int32 or int64:

private short[] GetShortArray(byte[] pBaits)
{
    int length = pBaits.Length / 2 + pBaits.Length % 2;
    short[] ret = new short[length];
    int j = 0;
    for (int i = 0; i < pBaits.Length; i += 2)
    {
        ret[j] = BitConverter.ToInt16(pBaits, i);
        j++;
    }
    return (ret);
}

Obviously for the  int32 you have to move 4 bytes, for int64 8 byte and so on.

short[] pippo = new short[] { 100, 156, 234, 322 };
byte[] pluto = new byte[pippo.Length * 2];
int j = 0;
for (int i = 0; i < pippo.Length; i++)
{
    byte[] pezzo = BitConverter.GetBytes(pippo[i]);
    pluto[j] = pezzo[0];
    j++;
    pluto[j] = pezzo[1];
    j++;
}

short[] resultShort = GetShortArray(pluto);

the awful test code above gives the following result:

convertino_02

I’m sure there are much elegant ways to extract bytes from a short array, and if the bytes composing the array arrive you from a serial port there is no need for my first fake conversion.

Convert a number in a string in binary format:

If you need to examine an integer or a byte to make an Or or a Xor, the better way is verify the bits composing it, of course, the Windows scientific calculator is a good helper, but if you have a whole array of numbers it is a little bit slow, fortunately in the .Net framework you have the necessary classes.

private string GetBitString(byte pVal)
{
    return (Convert.ToString(pVal, 2));
}

private string GetOctalString(byte pVal)
{
    return (Convert.ToString(pVal, 8));
}

I made 2 methods just because the second parameter is the numeric base for the number so 2 is binary 8 is octal, 16 is hexadecimal and so on. The result of my test is the following:

convertino_01

you can now verify[ 23+24+26 = 88] binary [0 + 3x81 + 1x82 = 88].

posted @ mercoledì 12 ottobre 2011 19.43 | Feedback (0)

domenica 9 ottobre 2011 #

Work with a simple HTTP Listener and avoid problems with BOM

We are implementing an internal service (internal means that it runs on an intranet) for one of our softwares that exchanges messages with my application clients when they run on the users machines. The data exchanged is sent as an XML class to an HTTP Listener.

It looked all simple and easy except that, when the XML class arrived to the Listener, the XML De-Serializer went nuts telling us the class was not correctly formatted.

After some checks to verify if we did something wrong (I always start from the principle that the probability I make a mess is higher than the one that compiler or libraries from third parties are wrong) and not finding nothing in the serialization and deserialization routines, sniffing the data arriving in the request, we discovered that the serialized data got 3 bytes preceding the <?xml which starts every xml data, in Hexadecimal EB BB BF, we didn’t understand what it was, and after a moment thinking to what could be wrong in our code to produce such problem, we made a search through the internet and learn something important (as always you never stop learning things…) Anyway, we discovered these three characters are a BOM (Byte order Mark) that is automatically added by the system serializing in UTF-8 encoding. Notepad, Notepad++ and other text editors/readers ignore it so you never notice it’s existence, but it is there. The problem in my service was that when deserializing from a string the three characters were not discarded so the Deserialize method gave an error telling that it found bad characters at the beginning of the class.

Is there a way to avoid the problem with BOM? Yes, it is one of the parameters of the XmlWriterSettings

XmlWriterSettings xstt = new XmlWriterSettings();

xstt.Encoding = Encoding.UTF8 : new UTF8Encoding(false);
using (XmlWriter writer = XmlWriter.Create(stream, xstt))
{
   ...
}

Using this option to serialize the class avoids the BOM and the deserialization problems.

Hoping to help someone else solving this problem faster Occhiolino

posted @ domenica 9 ottobre 2011 21.49 | Feedback (0)

mercoledì 5 ottobre 2011 #

The Phantom Password …

Between yesterday afternoon and today’s noon, two of us lost 4 x 2 = 8 hours of worktime to find the cause of the problem in this post’s subject. A class used many times in our projects suddenly stopped working it’s usual way giving strange error messages.

I’m testing some classes for a new application using a Test application, the classes are using a SQLServer database, since I need to test on multiple databases, I’ve put on a form a textbox with the connectionstring to be able to change it on the fly.

Data Source=NomeServer;Initial Catalog=NomeDatabase;Password=LaPassword;User ID=LUtente;

The connection string was set as the one above, of all  the tests I made, just one uses a DataProvider class, which contains a Dataset, with one DataTable, served by a SqlDataAdapter, 4 SqlCommand and a SqlConnection. This is the kind of classes we use for CRUD on all our tables and they work fine. Yesterday, an operation made of: Fill (call DataAdapter’s Fill), AddRow, Update (call to DataAdapter’supdate) gave an error telling that the user had no Login Rights on SQL Server.

After 3 hours debugging step by step,  we discovered that the DataAdapter, after calling the Fill cutted the password from the ConnectionString property of the SqlConnection class automatically. Being a class used on daily bases on all our applications we started wondering how was it possible that all worked correctly until yesterday.
After another hour of tests on various things, we debugged step by step one of our applications and we found out that we were not totally nuts, the difference was that the connection strings (built by a standard helper in all our applications) were made like the following one:

Data Source=NomeServer;Initial Catalog=NomeDatabase;Password=LaPassword;User ID=LUtente;Persist Security Info=true;

So, if a  DataAdapter after the first call to one of its commands, eats the password, this is why. If the Persist Security Info, which is by the way one of the Not recommended options, is not in the connectionstring, after the first Connection Open it is discarded automatically. On the documentation it is specified this is a logic thing made for security reasons. Anyway it is the kind of problem that makes you feel an idiot, asking yourself “How it is possible it never happened before?”

Tag di Technorati: ,

posted @ mercoledì 5 ottobre 2011 14.37 | Feedback (0)

martedì 27 settembre 2011 #

How to use IIS to debug a Service Application WCF on IIS 64Bit

This is as usual a post to avoid forgetting how to set up something you don’t do every day.

When you create a new Webservice using a WCF service application project, the system proposes automatically to debug it on the development webserver. But if you need to test the service from different machines especially if you work in team with somebody who is developing the client, it could be difficult to set up a connection to the development webservice, so it is easier to publish the application on IIS. To do it you need to modify the application configuration:

webapp_service_01

You need to select “Use local IIS Web Server”, confirm or change the project URL and click on Create Virtual Directory.

webapp_service_05

Important!!! After the previous setting, change also the Output Path to the bin\ instead of bin\debug or bin\x86\debug or things won’t work correctly for the .dlls referenced.

If you are working on a 64bit computer and your application is a 32 bit application, like in my case, you need to open the IIS manager.

webapp_service_02

Select the application pool used by the Webservice from the Application Pools list.

webapp_service_03

Click on the Application pool advanced settings.

webapp_service_04

activate the 32 bit applications and restart the Website.

If launching the webservice application you obtain the following screenshot:

webapp_service_06

Your webservice is working correctly you just need a startup page, but using the multiple startup projects from your
Solution > Right click > Properties

webapp_service_07 

You can start both the webservice and a test application where you can add a webreference to your service and debug it.

HTH

Tag di Technorati: ,,,

posted @ martedì 27 settembre 2011 18.00 | Feedback (0)

mercoledì 10 agosto 2011 #

HTTP Listener and XML

Today, working at a small project using the .Net object in the title, we found something weird; if I used an HTTP Get to send a string to the Listener and the string was a plain text like “Hello, I am the string”, it arrived exactly as it was sent, while if the string was the XML serialization of a custom object the result string was different when received and before the <?xml we found three characters, an i with an umlaot, a closing double quote, and an upside down question mark.
Digging into the string we found that the XML Serialization by default inserts as first character of a serialized string/file the unicode character  \UFEFF, which is a non visible character (also notepad does not show it), this character is necessary to the device/software/whatever that receives the text to determine if it is BigEndian or LittleEndian, You can find the details here on Wikipedia if you are curious. This unicode character can be omitted in serialization just asking it to the .NET serializer, changing a property in the XmlWriterSettings that you give to the XmlSerializer the property is Encoding=false to exclude the character.

It is not exactly a solution, but it is a good workaround if you cannot do more. The real solution is call an UrlEncoding of the XML string before sending it using the GET, or else, if you want to be sure everything remains unchanged, you can convert the XML string to BASE64 Using Encoding.Unicode to obtain a Byte Array from the string and then parse it when received from the listener.

Usually the exception you receive when this problem happens is the following:

System.Xml.XmlException
Data at the root level is invalid. Line 1, position 1.

here is the screenshot of the XML string with the problem.

xml_err

Tag di Technorati: ,,,

posted @ mercoledì 10 agosto 2011 16.48 | Feedback (0)

giovedì 26 maggio 2011 #

Associate more domains to a website generated using Plesk

It is probably well known from all those who use Plesk on a daily base, I instead use it rarely and I have a minimum knowledge of what functionalities it has. My company has rented a virtual server from a Hosting Provider, and as most of them do, they install Plesk by default on these servers probably to avoid millions of phone calls from unexpert users like me.

It is normal for a company own more than one domain (.it, .com, .net, .eu) and more, each mapped on the company’s site and obviously we don’t make a copy of the site for each domain, or it will be depressing to keep them updated.

In my case, the website has been created with DotNetNuke, which is so nice to allow not only the mapping of more domains on a single portal, but also, to make more portals on the same DNN.

When you open Plesk Administration console, and you want to create the secondary domains the thing that comes to my mind first is click on New Domain, bu that option has only 3 possibilities, Fisical Domain, Forward, Frame Forward, and it is not what we need for the use with our DNN.

What we have to do is click on the Domain that holds fisically the DNN and then use the Add Domain Alias option. This Creates an Alias on the Webserver, mapped on the same Website, it’s an operation very quick, just write the domain alias name and check the Web checkbox, then save.

Done this, you have just to open the DNN using the Host user and map the new domains as portal aliases on any DNN Portal you like.

Tag di Technorati: ,,,,

posted @ giovedì 26 maggio 2011 13.20 | Feedback (0)

venerdì 6 maggio 2011 #

TFS Correct an error in Time

It is something like Back to the Future applied to TFS 2010…

Last May 5th in our office we had a Blackout, the servers shut down and we had a problem with the master domain controller restart, no one noticed that all developer computers and the TFS server had the clock moved ahead to May 8th until someone took a look at his calendar asking himself why was he at office on a sunday. A bocca apertaA bocca apertaA bocca aperta.

The clock was corrected immediately but some Checkins were done during the Time Warp. We did not give importance to this thing until this afternoon when on a checkin we had this nice error message.

TF54000: Cannot update data because the server clock may have been set incorrectly. Contact your Team Foundation Server Administrator.

Being the administrator it was easy to contact myself, Con la lingua fuori but of course I had no solution, fortunately with an easy Bing search I found the following 2 solutions posted on Microsoft Forums:

  1. Wait to checkin after May 8th, could be done but it was not the best.
  2. Modify the Changesets with the wrong date on TFS database.

We obviously choosed the second option, so I put the script we used to solve the problem:

UPDATE tbl_ChangeSet
	SET CreationDate = CreationDate -3 WHERE CreationDate > GETDATE()

This moved back to May 5th all the changesets with date and time in the future and then the checkins worked correctly.

Tag di Technorati: ,

posted @ venerdì 6 maggio 2011 17.42 | Feedback (1)

martedì 29 marzo 2011 #

The solution to a small conversion problem

It’s not something we do on a daily base so I write it here to be able to find it when I need it.

A colleague asked me a question on how to convert a VB function in C#, this function calculates the checksum for a string that has then to be sent through a serial port.

The problem was that  VB converts a string “&HF6” to a short while my short.TryParse( “0xF6”, out val) don’t.

The problem is determined by the fact that as a default TryParse expects to receive a number and an Hexadecimal virtually isnt.

The solution is use the following:

val = Int16.Parse("0xF6", System.Globalization.NumberStyles.HexNumber);

Very easy, but it needed about half an hour finding and trying it, so I hope to help someone else spare that time Occhiolino

posted @ martedì 29 marzo 2011 15.10 | Feedback (0)

lunedì 17 gennaio 2011 #

Capture screenshots from multiple screens in C#

Today Stefano, a friend asked a question on our forum that looked very easy to answer.

“I Use Screen.PrimaryScreen to capture the screen in C# but I have a multiple screen environment (4 screens) and I need to capture them all. Any Ideas?”

The Answer was simple, Screen class has an AllScreens Property which is an array giving us all the screens connected to the PC, using that you can easily Capture Each screen image using a for cycle with the following code for each screen:

                Bitmap ps = new Bitmap(x.Bounds.Width, x.Bounds.Height);

                Graphics graphics = Graphics.FromImage(ps as Image);
                graphics.CopyFromScreen(x.Bounds.X, x.Bounds.Y, 0, 0, x.Bounds.Size);

                ps.Save(string.Format(@"c:\MultiImage{0}.jpg", i), ImageFormat.Jpeg);

                this.textBox1.Text += string.Format("DONE <{0}> ", i) + Environment.NewLine;

But what He really wanted was a single image containing the whole screen, the same thing you obtain using a printscreen.
And that’s not so simple.

Infact, I made a test with 2 screens, using my notebook, and Windows Vista and 7 (I don’t remember if XP made the same), when you have multiple screens allows you to position the secondary screens on whatever side of your primary screen you desire, changing consequently the properties indicating where the secondary screen (or screens) are positioned based on the primary one.

Because of this, composing an image is not so easy and requires some calculations, (of course you can use the clipboard if you prefer, but we are here to learn C# and use .NET right?).

This is what I ended up with:

            int width = 0;
            int height = 0;
            int minx = 0;
            int miny = 0;
            for (int i = 0; i < Screen.AllScreens.Length; i++)
            {
                Screen z = Screen.AllScreens[i];
                if (z.Bounds.X < minx) minx = z.Bounds.X;
                if (z.Bounds.Y < miny) miny = z.Bounds.Y;
                if (i == 0)
                {
                    width = z.Bounds.Width;
                    height = z.Bounds.Height;
                }
                else
                {
                    Screen p = Screen.AllScreens[i - 1];
                    //Sta a destra
                    if (z.Bounds.Right > p.Bounds.Right)
                    {
                        width += z.Bounds.Right - p.Bounds.Right;
                    }
                    else
                    {
                        //sta a sinistra
                        if (z.Bounds.Left < p.Bounds.Left)
                        {
                            width += Math.Abs(p.Bounds.Left - z.Bounds.Left);
                        }
                    }
                    //sta sopra
                    if (z.Bounds.Top < p.Bounds.Top)
                    {
                        height += (Math.Abs(z.Bounds.Top) - Math.Abs(z.Bounds.Bottom));
                    }
                    else
                    {
                        if (z.Bounds.Bottom > p.Bounds.Bottom)
                        {
                            height += z.Bounds.Bottom - p.Bounds.Bottom;
                        }
                    }

                }
            }

Based on the secondary screen position I’ve calculated the total image width and height and the offset of the bitmaps.

            Bitmap ps = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(ps as Image);

            this.textBox1.Text = "";
            for (int i = 0; i < Screen.AllScreens.Length; i++)
            {
                Screen x = Screen.AllScreens[i];
                this.textBox1.Text += string.Format("------------------->{0}<-------------------------", i)
+ Environment.NewLine; this.textBox1.Text += "Top:" + x.Bounds.Top.ToString() + Environment.NewLine; this.textBox1.Text += "Bottom:" + x.Bounds.Bottom.ToString() + Environment.NewLine; this.textBox1.Text += "Left:" + x.Bounds.Left.ToString() + Environment.NewLine; this.textBox1.Text += "Right:" + x.Bounds.Right.ToString() + Environment.NewLine; this.textBox1.Text += "X:" + x.Bounds.X.ToString() + Environment.NewLine; this.textBox1.Text += "Y:" + x.Bounds.Y.ToString() + Environment.NewLine; this.textBox1.Text += "Width:" + x.Bounds.Width.ToString() + Environment.NewLine; this.textBox1.Text += "Height:" + x.Bounds.Height.ToString() + Environment.NewLine; this.textBox1.Text += string.Format("-------------------<{0}>-------------------------",
i) + Environment.NewLine; graphics.CopyFromScreen(x.Bounds.X, x.Bounds.Y, x.Bounds.X + (Math.Abs(minx)),
x.Bounds.Y + Math.Abs(miny), x.Bounds.Size); ps.Save(@"c:\SingleImage.jpg", ImageFormat.Jpeg); this.textBox1.Text += string.Format("DONE <{0}> ", i) + Environment.NewLine; }

Then I compose the bitmap joining the two pieces of screen. I’m sure there is a better way of doing it, and of course
You probably need to change some things to make it work with three or more screens.
If you try it, let me know.

Technorati Tag: ,

To download the code, Log in and go to resources area

posted @ lunedì 17 gennaio 2011 19.38 | Feedback (0)

giovedì 6 gennaio 2011 #

E’ arrivata la Befana…

Sorry for the Italian title but there isn’t a translation for that.

I had no time to read my personal mail account from last friday, this morning, opening outlook I found two messages from Alessandro Teglia of Microsoft and… I fell from the chair …  Open-mouthed smile it was the announcement of the MVP Award. So, aunt Yeye has arrived among MVPs. It is obviously something that makes you feel like walking ten inches from earth, it is not something happening every day, to receive an award recognizing your professional competence known all over the planet. So now all it comes to my mind is some sort of an Oscar speech, of course it would be ridiculous, so thanks to the MVP program people at Microsoft to acknowledge my 23 years of work with Microsoft technologies, a job that is still exciting and gripping as on my first day in front of an IBM XT trying the DOS commands to see how they work while reading the Operating System Manual.

P.s. This:

 befana is a Befana.

She brings candies to the good kids in Italy on January 6th and brings Carbon to the bad kids.

posted @ giovedì 6 gennaio 2011 19.31 | Feedback (3)

giovedì 30 dicembre 2010 #

Using Date differences to build a countdown to new year

A small application inspired by Stefano Pranzo, to create a countdown to new year.

 

frmcountdown

The final result is shown in the above image, to create it we have to create a new Windows Forms Application, rename its Form1 to FrmCountdown and change the following properties:

  • BackgroundImage –>Choose an image from your disk using the 3 dots button and import it into the project resources. I’ve found the above one writing newyear on the bing image search.
  • BackgroundImageLayout –> Stretch
  • FormBorderStyle –> None
  • KeyPreview –> True (we will use it to manage quit application).

We add a label to the form named lblCountdown with the following properties:

  • BackColor –> transparent
  • Font Name –> Lucida Calligraphy
  • Font Size –> 64
  • Forecolor –> Gold
  • TextAlign –> MiddleCenter

We add a button to the form named btnClose with the following properties:

  • UseVisualStyleBackColor –> False
  • FlatStyle –> Flat
  • BackColor –> transparent
  • Font Name –> Lucida Calligraphy
  • Forecolor –> Gold
  • Text –> Close

We add to the form a timer named tmrCountdown.

The code behind the form is the following:

        public FrmCountDown()
        {
            InitializeComponent();
            tmrCountdown.Interval = 1000;
            tmrCountdown.Enabled = false;
        }

In the form constructor we set the timer to an interval of 1000 milliseconds.

        private void FrmCountDown_Load(object sender, EventArgs e)
        {
            tmrCountdown.Start();
        }

On the Load  event of the form we activate the timer.

        private void btnClose_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

On the click event of the Close button we implement the application exit.

        private void FrmCountDown_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Application.Exit();
            }
        }

On the key Up event of the form we implement the application exit if  Esc key is pressed.

        DateTime mDtEnd = new DateTime(2011, 01, 01, 0, 0, 0);

We set a DateTime variable at form level with the final date and time, so 00:00:00 of january first.

        private void tmrCountdown_Tick(object sender, EventArgs e)
        {
            TimeSpan sp = mDtEnd.Subtract(DateTime.Now);
            this.lblCountdown.Text = sp.TotalHours.ToString("###") + ":" + 
sp.Minutes.ToString("0#") + ":" + sp.Seconds.ToString("0#"); Application.DoEvents(); }

Finally on the Tick event of the timer we update  our label calculating a difference between present date and time and the final date and time, converting then the data in a formatted string. As you can see we use the Subtract method of the DateTime class and the properties TotalHours, Minutes and Seconds of the Timespan representing the difference between the two dates.

Our NewYear Countdown is ready to go.
You can find the full project with working code in the resources area Cpde for Countdown

Happy newyear Everybody!

Technorati Tag: ,

posted @ giovedì 30 dicembre 2010 11.49 | Feedback (0)

lunedì 1 novembre 2010 #

Working with XML part 2

What the system offers for free

As I explained in previous post, .NET is very XML friendly, so it gives us a few base functionalities to avoid us doing things already done, here we say it saves us from inventing hot water. To demostrate the basic functionalities I build a simple, fundamentally useless class that demonstrates us how the basic data types of .NET are all serializable.

using System;
using System.Text;
namespace DnwEnitities.Entities
{
    public class Serializzabile
    {

        public Serializzabile()
        {
            TheChar = 'A';
            TheByte = 10;
            TheBool = true;
            TheShort = 100;
            TheInt = 1000;
            TheLong = 1000000;
            TheFloat = 1234.7899f;
            TheDouble = 9800000.89600;
            TheDecimal = 766000000.654390001m;
            TheString = "The string is very nice and useful.";
            TheDate = DateTime.Now;
            TheGuid = Guid.NewGuid();
            TheEnum = SerializableEnum.ALot;
        }
    
        public char TheChar
        {
            get;
            set;
        }

        public byte TheByte
        {
            get;
            set;
        }

        public bool TheBool
        {
            get;
            set;
        }

        public short TheShort
        {
            get;
            set;
        }

        public int TheInt
        {
            get;
            set;
        }

        public long TheLong
        {
            get;
            set;
        }

        public float TheFloat
        {
            get;
            set;
        }

        public double TheDouble
        {
            get;
            set;
        }

        public decimal TheDecimal
        {
            get;
            set;
        }

        public string TheString
        {
            get;
            set;
        }

        public DateTime TheDate
        {
            get;
            set;
        }

        public Guid TheGuid
        {
            get;
            set;
        }

        public SerializableEnum TheEnum
        {
            get;
            set;
        }

        public static Serializzabile ReadXml(string pSerializedData, bool pIsXmlData)
        {
            Serializzabile retP = null;
            if (!pIsXmlData)
            {
                retP = (Serializzabile)SerializeHelper.DeserializeFromFile(
typeof(Serializzabile), pSerializedData); } else { retP = (Serializzabile)SerializeHelper.DeserializeFromString(
typeof(Serializzabile), pSerializedData); } return (retP); } public virtual void WriteXml(string pFileName) { SerializeHelper.SerializeToFile(pFileName, this, typeof(Serializzabile), false, string.Empty); } public virtual string WriteXml() { return (SerializeHelper.SerializeToString(this, false, string.Empty)); } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Char: {0}", this.TheChar); sb.AppendLine(); sb.AppendFormat("Byte: {0}", this.TheByte); sb.AppendLine(); sb.AppendFormat("Bool: {0}", this.TheBool); sb.AppendLine(); sb.AppendFormat("Short: {0}", this.TheShort); sb.AppendLine(); sb.AppendFormat("Int: {0}", this.TheInt); sb.AppendLine(); sb.AppendFormat("Long: {0}", this.TheLong); sb.AppendLine(); sb.AppendFormat("Float: {0}", this.TheFloat); sb.AppendLine(); sb.AppendFormat("Double: {0}", this.TheDouble); sb.AppendLine(); sb.AppendFormat("Decimal: {0}", this.TheDecimal); sb.AppendLine(); sb.AppendFormat("String: {0}", this.TheString); sb.AppendLine(); sb.AppendFormat("Date: {0}", this.TheDate); sb.AppendLine(); sb.AppendFormat("Guid: {0}", this.TheGuid); sb.AppendLine(); sb.AppendFormat("Enum: {0}", this.TheEnum); sb.AppendLine(); return (sb.ToString()); } } public enum SerializableEnum : int { None = 0, All, Some, ALot } }

This class represents the most raw and simple entity, it contains some public properties, one for each of the base data in .NET, it contains the WriteXml and ReadXml methods, using our Helper to write and read in XML the content of the class and an override of the ToString method that helps us visualize the class contents. There is also a simple Enumeration, showing us that enumerable values are serialized automatically.

Instantiating a class of Serializzabile type, and calling its WriteXml method to write its content to a file, the content of the file is the
following:

<?xml version="1.0" encoding="utf-8"?>
<Serializzabile xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <TheChar>65</TheChar> <TheByte>10</TheByte> <TheBool>true</TheBool> <TheShort>100</TheShort> <TheInt>1000</TheInt> <TheLong>1000000</TheLong> <TheFloat>1234.78992</TheFloat> <TheDouble>9800000.896</TheDouble> <TheDecimal>766000000.654390001</TheDecimal> <TheString>The string is very nice and useful.</TheString> <TheDate>2010-11-01T09:26:13.331+01:00</TheDate> <TheGuid>3da90b04-ec02-4308-a177-fc6723ab8aa9</TheGuid> <TheEnum>ALot</TheEnum> </Serializzabile>

Using the ReadXml  to re-read the class, we will obtain an equivalent object. If we haven’t any particular requirement to satisfy in our programs, this is the simplest way to build a serializable entity.

Technorati Tag: ,,

posted @ lunedì 1 novembre 2010 10.04 | Feedback (1)

Moving a Team Foundation Server 2010 from a domain to another

This is the list of what we did a couple of weeks ago in my organization, moving our development TFS from a domain to another domain, I write it here in case someone else needs it and of course to find it out if I ever need this again.

First thing to do is read carefully the TFS documentation on this matter, starting with the MSDN document titled Move Team Foundation Server from One Environment to Another and reading carefully what to do in your specific case. Our move was the simplest one, We needed to move Our Single Server from domain XXX to domain YYY without changing anything.

The first thing we did was a full backup of all the TFS databases from our SQL Server 2008. Then, we did a Ghost of the Server Hard Disk, to be sure to have the possibility to Rollback in case of problems.

Then the procedure we followed was this:

  • We created the same service users we had on our present environment on the new domain, this means, the TfsService user, the SQLService user, the Proxy User and other domain users required by the system and we give them the same passwords.
  • We opened the TFS configuration and write down on a notepad all user groups and all TFS groups and WIndows groups and users mapped to every TFS project inside our server paying attention to write down everything. This operation is important because the Group and User mapping on project will be cleared during the moving and to avoid developers from “Screaming” and “cursing you” because they’ve lost access to their projects you have to be careful on this.
  • Another important thing to remember is DO NOT CHANGE THE NAME OF THE SERVER IN THE NEW ENVIRONMENT this is Very Important, because SQL Server 2008 has some problems when you rename its instance under it’s nose. So if you change the servers naming in the new domain, for your sake, move your old servers with the same name and let them Die with that name.
  • After this, You have to kill the TFS services, you can do that using the TFSServiceControl command line utilities which is located under the Tools folder of the TFS 2010 installation folder.
    TfsServiceControl quiesce 
    is the command to shut down the services.
  • You also have to shut down IIS if you have sharepoint on the same machine and SQL Server services.
  • Now you have to move the server to the new domain, Remember to activate a local system Administrator User with a simple password, use a domain administrator with the rights to do so to remove the server from the old domain. Restart it, verify that the services are still stopped or stop them again using the local Administrator.
  • Remember also to activate the SA user with a password you know or to create a SQL Server user with SysAdmin rights giving it a password of your choice.
  • Join the server to the new domain. Change the Service users for SQL Server and TFS services to the one in the new domain and start SQL Server, do not yet start TFS.
  • Then you first need to open the SQL Server Management Studio and log on using SA or your personal Sysadmin, go to the Security folder and verify that local machine Windows Groups have mantained their rights. Then map the new domain Windows Groups or users you had on the old domain and assign them rights and roles on the TFS databases. Remove database mappings from the old users before deleting them.
  • You also need to go to the Users management of the local Server, and if you created local groups containing domain users or groups, you need to remap the users and groups from the new domain.
  • Then you need to use the Identities Command, which is one of the options provided by the TFSConfig command line utility of TFS to change inside the configuration database of TFS the SIDs of the Domain Users used to run TFS Services, the utility stays on the Tools folder of the TFS installation. There is an article on the msdn linked to the guide I linked at the beginning of this article that gives you all the informations on how to use it. The command is something like:
    TFSConfig Identities /change /fromdomain:olddomain /todomain:newdomain /account:accountname /toaccount:accountname
                               /sqlinstance:sqlserverinstancename /databasename:TfsConfigDatabase /account:sqlaccountname
    If you Kept instance names and user names and passwords identical on the two domains this is a simple routine operation and all works at first shot. So keep clearly in mind, no Server name change, no service user change, no password change.
  • In the unfortunate case you had to change a service user, there is another command of the TFSConfig utility, named Accounts, you can use to specify to TFS the new service accounts before executing the Identities command.
  • After this you can restart TFS using the TfsServiceControl unquiesce command.
  • Open the TFS configuration manager, go back to the User Access and permission configuration and restore for each project the Windows Users and groups and the TFS users and Groups that have been erased by the domain move. With a particular care for the Project collection valid users, Team Foundation Licensed Users whicy you find if your first installation was a Workgroup TFS is no more needed.

After this procedures are completed, you can open a Visual Studio 2010 and attach to the TFS client from a computer in the new domain, if you did all well, the server will respond exactly as it responded on the old domain.

I didn’t speak of Sharepoint, well we are a small team and don’t use sharepoint, but the migration guide gives you all the instruction to migrate also Sharepoint services, so I’m sure it works correctly.

Technorati Tag: ,

posted @ lunedì 1 novembre 2010 8.23 | Feedback (2)

domenica 31 ottobre 2010 #

Working with XML part 1

This is the first of a small series of posts dedicated to XML serialization, publishing the code I used for the last Workshop we did last month. I’ll start from the serialization Helper class, already discussed in the past, now revised for Framework 4.0.

To persist on a disk a C# (orVB) class, you need to create it with some simple tricks to make it serializable. Serialization is a word I’ve started to listen around 2003 at the first conferences on .NET I attended to. Maybe it’s self explanatory for an English mother tongue, but it wasn’t for me. I needed a while to understand that Serialization is the way to persist on mass storage the state of an object to be able to rebuild the same object with the exactly same state as the one we persisted on disk.

Entity classes are classes with no particular abilities, they are defined this way because they represent structured data, so entities are the classes representing a Data Model, it can be simple and persisted on a file, or complex, like a LinqToSql or EntityFramework model persisted on a database. Entities are the kind of class we will surely serialize someway.

In .NET, you can serialize data in 2 ways, binary serialization and XML serialization. All the base data types in .NET are serializable, so any class containing only this kind of data, can be directly serialized with no particular modification except it needs to implement a parameterless constructor.

What is automatically serialized by .NET in an object? The public properties. Why only these? I think it is because they represent the state of the object as it can be observed by who instantiated it, we can always modify the standard behaviour overriding the default serialization. In these articles we will however show only how to use the standard serialization and how to drive it how we desire just using a few simple functionalities given us by the framework itself.

SerializeHelper class

This class provides all serialization services for simple object and composite objects (collections or classes containing other classes). It uses the classes of the System.Xml and System.Xml.Serialization namespaces. Let’s see its methods.

BuildReader

        public static XmlTextReader BuildReader(string pXmlString)
        {
            NameTable nt = new NameTable();
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
            nsmgr.AddNamespace("bk", "urn:sample");

            XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);

            return (new XmlTextReader(pXmlString, XmlNodeType.Element, context));
        }

This first method, as it's name says, creates an XmlTextReader, that together with the correspondent XmlTextWriter are the base streams for reading and writing XML data. The method above has been designed to allow us to transform a string (such as a database field) in an Xml stream. The method generates a “fake” context to build the XmlTextReader to transform the string in a stream.

DeserializeFromString

        public static object DeserializeFromString(Type pTypeToDeserialize, string pXmlString)
        {
            object ret = null;
            using (XmlReader xr = BuildReader(pXmlString))
            {
                XmlSerializer serializer = new XmlSerializer(pTypeToDeserialize);
                ret = serializer.Deserialize(xr);
                xr.Close();
            }
            return (ret);
        }

        public static object DeserializeFromString(Type pTypeToDeserialize, 
Type[] pExtraTypes, string pXmlString) { object ret = null; using (XmlReader xr = BuildReader(pXmlString)) { XmlSerializer serializer = new XmlSerializer(pTypeToDeserialize, pExtraTypes); ret = serializer.Deserialize(xr); xr.Close(); } return (ret); }

These two methods, one built for a class with only simple objects, another for a class with complex data types, use the previous method to create a stream that is then passed to the XmlSerializer class to get the object from the persisted string.

DeserializeFromFile

        public static object DeserializeFromFile(Type pTypeToDeserialize, string pPath)
        {
            object ret = null;
            using (XmlTextReader reader = new XmlTextReader(pPath))
            {
                // Occorre un'istanza della classe XmlSerializer
                XmlSerializer serializer = new XmlSerializer(pTypeToDeserialize);
                // e questo é tutto ciò che serve per leggere i dati dal formato XML
                ret = serializer.Deserialize(reader);
                reader.Close();
            }
            return (ret);
        }

        public static object DeserializeFromFile(Type pTypeToDeserialize, 
Type[] pExtraTypes, string pPath) { object ret = null; using (XmlTextReader reader = new XmlTextReader(pPath)) { // Occorre un'istanza della classe XmlSerializer XmlSerializer serializer = new XmlSerializer(pTypeToDeserialize, pExtraTypes); // e questo é tutto ciò che serve per leggere i dati dal formato XML ret = serializer.Deserialize(reader); reader.Close(); } return (ret); }

The deserialization from a file is simpler, because XmlTextReader has a constructor that builds it from a file path. The two overloads of this method allow us to specify to the XmlSerializer the classes used if the objects involved are not simple classes. We will see it’s use when we will deserialize collections, but collections are not the only complex classes we will see.

SerializeToFile

        public static void SerializeToFile(string pPath, object pObjToSerialize, 
Type pTypeToSerialize, bool pNoNamespaces, string pPrefix) { FileInfo fInfo = new FileInfo(pPath); if (!Directory.Exists(fInfo.DirectoryName)) { Directory.CreateDirectory(fInfo.DirectoryName); } using(XmlTextWriter writer = new XmlTextWriter(pPath, Encoding.UTF8)) { // write a readable file writer.Formatting = Formatting.Indented; writer.Indentation = 4; // Occorre un'istanza della classe XmlSerializer XmlSerializer serializer = new XmlSerializer(pTypeToSerialize); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); string prefix = pPrefix != null ? pPrefix : string.Empty; if (pNoNamespaces) { ns.Add(prefix, TXT_Namespace); } // e questo é tutto ciò che serve per persistere i dati serializer.Serialize(writer, pObjToSerialize, ns); writer.Close(); } } public static void SerializeToFile(string pPath, object pObjToSerialize, Type pTypeToSerialize, Type[] pExtraTypes, bool pNoNamespaces, string pPrefix) { FileInfo fInfo = new FileInfo(pPath); if (!Directory.Exists(fInfo.DirectoryName)) { Directory.CreateDirectory(fInfo.DirectoryName); } using(XmlTextWriter writer = new XmlTextWriter(pPath, Encoding.UTF8)) { // write a readable file writer.Formatting = Formatting.Indented; writer.Indentation = 4; //writer.Settings.OutputMethod = XmlOutputMethod. // Occorre un'istanza della classe XmlSerializer XmlSerializer serializer = new XmlSerializer(pTypeToSerialize, pExtraTypes); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); string prefix = pPrefix != null ? pPrefix : string.Empty; if (pNoNamespaces) { ns.Add(prefix, TXT_Namespace); } // e questo é tutto ciò che serve per persistere i dati serializer.Serialize(writer, pObjToSerialize, ns); writer.Close(); } }

For the serialization, we made the two overloads with informations on the classes and we added a few parameters that allow us to format the classes, pNoNamespaces and pPrefix.

In the code we can see how, creating the XmlTextWriter we can decide the Encoding used for the generated string, our method uses UTF8 standard serialization but if we need something else we can use another encoding. We can also control the Xml File formatting both using the Formatting Property and some other properties to determine indentation and indentation character.

The use of XmlSerializerNamespaces allows us to avoid the verbose series of the namespaces inserted automatically in the first element of a serialized class:

<Serializzabile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

Replacing this with:

<Competences xmlns="http://www.dotnetwork.it">

Or, using the Nonamespace flag:

<Competences>

“killing” the namespaces is opportune to create neutral classes for data exchange between different companies and softwares, while if we want to be sure that our own classes are marked specifically to make them unique, we can add our namespace (usually it is the domain name of our website).

the pPrefix parameter has instead the purpouse to allow us to set a prefix on the name of our classes to obtain the following effect:

<dnw:Programmer xmlns:dnw="http://www.dotnetwork.it">

<dnw:Skills>

It allows us to specify in detail the use of our own objects without a full namespace attribute on each of them.

SerializeToString

        public static string SerializeToString(object pObjToSerialize, 
Type[] pExtraTypes, bool pNoNamespaces, string pPrefix) { string ret = string.Empty; using (MemoryStream stream = new MemoryStream()) { XmlSerializer serializer = new XmlSerializer(pObjToSerialize.GetType(), pExtraTypes); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); string prefix = pPrefix != null ? pPrefix : string.Empty; if (pNoNamespaces) { ns.Add(prefix, TXT_Namespace); } serializer.Serialize(stream, pObjToSerialize, ns); ret = Encoding.UTF8.GetString(stream.ToArray()); stream.Close(); } return (ret); } public static string SerializeToString(object pObjToSerialize, bool pNoNamespaces, string pPrefix) { string ret = string.Empty; using (MemoryStream stream = new MemoryStream()) { XmlSerializer serializer = new XmlSerializer(pObjToSerialize.GetType()); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); string prefix = pPrefix != null ? pPrefix : string.Empty; if (pNoNamespaces) { ns.Add(prefix, TXT_Namespace); } serializer.Serialize(stream, pObjToSerialize, ns); ret = Encoding.UTF8.GetString(stream.ToArray()); stream.Close(); } return (ret); }

The last method, with two overloads, allows us the Xml serialization of an object on a string instead of serializing it on a file stream. To be able to do so we need however a stream, we use the MemoryStream to avoid a file on disk, the Xml generation remain identical to the one that builds a file on disk.

Technorati Tag: ,,,

posted @ domenica 31 ottobre 2010 23.46 | Feedback (0)

domenica 17 ottobre 2010 #

Remote debugging from Visual Studio 2010 some tips on real world experience.

This is a shadow post, I write all here as always to be able to find it when I need it, but I’m just the writer, the real experiment was done by my colleague Luca, who loves writing code but hates writing documentation, blogs, articles and speech in public conferences… I still hope to convince him open a blog but my chances are poor.

Anyway this is it:

We had a strange behaviour on a machine for a new installed application, the machine was on a different domain from the development machines, and we wanted to remote debug it, here is what we did:

On the remote machine you want to debug you start mswsmon, the remote debug utility.
on tools>options you can choose between:

  1. No Authentication
  2. Windows Authentication

Choosing number one, you can debug, but we were not able to load debug symbols, so searching for the problem was not easy not having code to look for. Even copying the .pdb files on the installation folder was useless.

Choosing number two, being the destination machine on a different domain we had to do the following:

  1. Create a local user on development machine and remote machine with administrator privileges and same password. Even though on the remote machine we think you just need Remote debug permissions.
  2. Disable the firewall on both machines (We are sure we needed just a couple of ports enabled, but had no time to search them, and being on the same network, in the same office it was easier to do).
  3. Using mswsmon, on the remote machine, logged with the user that had the problem with the application, create a server named UserName@MachineName where UserName is the name of the local user created on point 1. Start the application to debug.
  4. Log on the development machine with the local user and password, open Visual Studio 2010, open remote debug using
    Debug>Attach to process, choose:
    • Transport = default (Windows Authentication)
    • Qualifier = UserName@MachineName (the one set on point 3)
    • Search for the process, double click and confirm.
    • You are now attached to the process running on the remote machine.
  5. We experimented also that if you have the same version of the program on Remote and Development machine, if you don’t have the .pdb files on the remote machine, you can use Debug>Windows>Modules window to search for the module or dll you are attached to and using context menu (right click) you can load symbols (PDB) from a file on the development machine.

posted @ domenica 17 ottobre 2010 15.31 | Feedback (1)

Database owner change

Yesterday I was in the middle of a very rare kind of operation in my company IT System, we are changing our Domain, moving all computers and servers from a domain to another.

One of the servers we moved is the TFS development server on which there is a SQL Server 2008 holding all our code and projects. The move to the new domain gave no problems at all, but as recommended we did not change the computer name.

After the move we had to add the domain users and groups of the new domain to SQL Server replacing the domain users and groups of the old domain and we had no troubles in doing this operation except for one thing.

Accessing the Properties of a database I had an error because the Database Owner was invalid and the Properties window for that database did not open at all.

The problem is due to the fact that databases are Owned by the User that creates them, and the TFS Databases were owned by the user used for the installation. I suggest to those who administer a TFS SQL server to change the Database Owner to SA for all databases.

Anyway it is not a big trouble, to take ownership of databases, what you need is to log in as a Sysadmin (SA would be the better), onto SQL Server and run the following script changing the USE clause to each database with Ownership problems and run it.

use DatabaseName
exec sp_changedbowner 'sa'

Technorati Tag: SQL,TSQL,Database

posted @ domenica 17 ottobre 2010 15.03 | Feedback (0)

domenica 10 ottobre 2010 #

DNN: How to use a page just as a menu option

Today I’ve lost about half an hour trying to remember how to create a page on DNN just to use it as a menu option. So I write here how to do it to remember it for the next time :P.

If my previous definition was not clear let’s use a sample of what I needed to do to make it clear:

My goal was to build a Top level Menu named Association which gives access to several sub menus, Who we Are, Our Board of directors, Associates, Messageboard and more.

Association +
            |
            +--- Who we are +
            |               |
            |               + Mission
            |               |
            |               + Board of directors
            |               |
            |               + Members
            +--- Messageboard
            |
            +--- Newsletters

In Dnn to made this structure in menus you need to build a page for each option even if the page is not a real page like Association and WhoWe Are in my structure above.

To avoid that users, clicking on Association without waiting the menu to open and show them the sub items, find themselves on a blank page, what you need to do is the following:

  1. Open Admin ->Pages options.
  2. Click on Association in the list.
  3. Click the Modify Icon.
  4. Open the Advanced Options collapsed section.
  5. Scroll down to the Link URL Section.

dnnurlpage

Set the URL to a page of your site (like the Board of Directors in my structure), or else build a fake URL (“#”) to keep user on current page. Save changes and you are done.

To undo this, if you need it you have to open the pages section under Admin, because neither the administrator or host has direct access to the page.

Technorati Tag:

posted @ domenica 10 ottobre 2010 15.15 | Feedback (0)

giovedì 16 settembre 2010 #

Configure SQL Server Database Mail to send Job Notifications

Today I was modifying the configuration of database mail on one of my company’s SQL Servers, so I decided to configure the Database mail on another server where it wasn’t yet configured. Being something made once every five years or more, I decided to publish the steps to do it, this way I can repeat the operation on my customers servers to be sure someone is alerted if something on the SQL Server goes wrong.

My server is a SQL 2008 server, but the configuration is identical for SQL 2005.

tfsmail01

Open the Server Management folder on SQL Management Studio and select Database Mail.

tfsmail02

If it is the first configuration, leave the option as selected, elsewhere select the proper option and click NEXT.

tfsmail03

Give the profile a proper name and description, Database Mail can be configured for other tasks then the simple Job notification, and you can have more than a single profile for the different tasks.

tfsmail04

Click on the ADD button to create a mail account that has to be used to send the e-mails, pay attention, if you already have an account the Window above does not appear automatically, it appears first a window to select an existing account with a button that allows you to create a new one that opens this window.

tfsmail05

Fill in the account data with a name and a description, set the e-mail addresses and the SMTP server name and then fill the authentication credentials if necessary or leave the anonymous authentication (for example if the company SMTP server is configured to allow so).

tfsmail06

Then you need to set the security data for the profile, to be able to send e-mails from the SQL Server Agent, it’s better to create a public profile.

 

tfsmail07

After clicking the NEXT button, you’ll see two verification and execution confirm windows, the latter shown above.

tfsmail08

Now select the Operators Folder inside the SQL Server Agent Objects folder and create a new Operator.

tfsmail09

We just need to set the operator name and the e-mail where to send notifications, unless you want to set also Net Send and Pager for the operator.

tfsmail10

In Every backup, Maintenance or Script Execution Job set inside the Agent, you need to set up the Operator, Check the E-Mail notification action and set wether to notify Job Completion or Just Job Error or Job Success.

tfsmail11

Now we need to right click the SQL Server Agent icon and select the Alert System, activating the Database mail profile we generated. If you don’t do this operation, the Agent ignores E-Mail notifications and does nothing, it does not give any error or warning message.

tfsmail12

After the configuration of the Alert System you must Restart SQL Server Agent to activate the E-mail notification system for Jobs and Alerts.

posted @ giovedì 16 settembre 2010 16.16 | Feedback (4)

giovedì 9 settembre 2010 #

Just for fun, if you ever asked yourself why they call them Bugs…

Today we found this nice explanation on the wikipedia.

firstbug

it was indeed a bug :D :D :D

http://en.wikipedia.org/wiki/Software_bug  to read the full article on wikipedia.

And if you don’t know what is a relay, this is a sample, that’s why in 1945 a computer was large as a room ;P;P;P

Un Relay

And if you need a DeBugger…

bug

this is patented :D

Tags: ,

posted @ giovedì 9 settembre 2010 16.24 | Feedback (0)

venerdì 13 agosto 2010 #

Collection and predicates search elements without cycling

Among the most useful things when you work with collections, are Search methods, allowing us to find an element inside the collection using the value of one or more of his properties as a search criteria.

These methods can be implemented both as Indexer (a property) or a specific method. The second option is necessary because often there are more properties of the same data type used to search a collection and you can implement only one indexer with a certain signature.

Let’s work through some samples to see how to use predicates:

Our Entity class, named AnagraficaAzienda, exposes the following properties:

string DescrizioneRicerca //SearchDescription
string RagioneSociale //Company name
string PartitaIva //Vat Code
string Indirizzo //Address
string CAP //Zip code
string Citta //City
string PV //State or province
int IDTipo //Type
int IDAnagrafica //Identity

To create an Indexer to search through the SearchDescription we can use the following code:

public AnagraficaAzienda this[string pDescrizioneRicerca]
{
    get
    {
        return( Find(item=>item.DescrizioneRicerca==pDescrizioneRicerca);
    }
}

to create a method to get all elements that match a regular expression we can use the following code:

public List<AnagraficaAzienda> FindWithRegEx( string pRegEx )
{
    return (FindAll(items => Regex.Match(items.RagioneSociale, pRegEx).Success));
}

to create a method that returns the data using the Vat Code (PartitaIva) we can use the following code:

public AnagraficaAzienda FindXPartitaIva(string pPartitaIva)
{
    return( Find(item=>item.PartitaIva==pPartitaIva);
}

To create a multi dimensional indexer we can use the following code

public AnagraficaAzienda this[int pIDZona, int pIDAnagrafica]
{
    get
    {
        return( Find(item=>item.IDZona==pIDZona && item.IDAnagrafica==pIDAnagrafica);
    }
}

as you can see, a Predicate allows us to use any kind of binary expression to match the entity fields with the search criteria we want to use.

posted @ venerdì 13 agosto 2010 17.29 | Feedback (0)

martedì 10 agosto 2010 #

How to create a Guid.Empty in SQL

Last friday my colleague Luca was “fighting” with a problem in managing null values and GUIDs. A Guid is a value type so it is not nullable. In my stored procedures when using parameters for filtering, I use the NULL value as the default value to ignore a filter parameter.

Changing the code of several classes to be able to change a Guid.Empty into a DbNull before passing it to a SELECT command was decisely not the best thing to do, so we searched a way to recreate a Guid.Empty value in SQL.

We were able to create the small snippet of SQL in the following function:

CREATE FUNCTION Guid_Empty()
RETURNS UniqueIdentifier
AS
BEGIN
RETURN cast(cast(0 as binary) as uniqueidentifier)
END
GO

After the creation of the above function and a simple table on my Paperinik Database,  I was able to write the following query:

SELECT [ID]
      ,[Descrizione]
      ,[Prezzo]
      ,[Quantità]
      ,[Umi]
      ,IsNull(AltGuid, dbo.Guid_EMPTY()) AS Alt
  FROM [paperinik].[dbo].[TbRighe]

The query produces the following output:

guidquery

I can use it also to build a query like the one below:

SELECT [ID]
      ,[Descrizione]
      ,[Prezzo]
      ,[Quantità]
      ,[Umi]
      ,IsNull(AltGuid, dbo.Guid_EMPTY()) AS Alt
  FROM [paperinik].[dbo].[TbRighe]
WHERE
IsNull(AltGuid, dbo.Guid_EMPTY()) = dbo.Guid_EMPTY()

That allows me to filter only the Guid Empty rows, or I can use the <> to find only the rows with a non Empty Guid. This way of writing the query, is giving me the possibility to use Guid.Empty in my Code as a SQLParameter value without the need to use a Nullable Guid or to implement complicated control expressions in my C# classes.

Technorati Tag: ,,

posted @ martedì 10 agosto 2010 22.53 | Feedback (0)

lunedì 9 agosto 2010 #

Access the Deleted Rows of a Datatable

Today, I’m updating the Code Generator I’ve made in 2006 to build automatically the Data Provider classes for my applications. I’m passing my applications to Framework 4.0 and instead of a simple framework change, I’ve decided to make some cleaning in Old Common Libraries code and add some new features in the Data Classes.

One of the new features in my data classes, will be some events, raised when data operations complete, RowAdded and RowDeleted events are two of them. In both cases, it would probably be useful if you Handle the Event in your code, to have some informations on the Added Row or Deleted Row, so I decided to pass the whole DataRow as a property of the event argument.

Pass the Added row as an argument is very simple, I have the object in my method.

Pass the Deleted row is a little less simple. I’ve made a simple test project to find out how to get it, to be precise, the exact phrase is: How to get a copy of it.

The sample form is the following:

righecancellate

On the form there are 3 buttons – Carica = Load, Test Aggiunta = Test AddRow, Test cancellazione = Test Deletion. There is also a textbox, set as Multiline with vertical scrollbar.

The test code is the following:

        DataTable mDt;
        private const string FLD_ID = "ID";
        private const string FLD_Description = "Description";
        private const string FLD_Date = "Date";
        private const string FLD_Price = "Price";

        public Form1()
        {
            InitializeComponent();
            mDt = new DataTable("Tbtest");
            DataColumn col = new DataColumn(FLD_ID, typeof(int));
            col.AutoIncrement = true;
            col.AutoIncrementSeed = 1;
            col.AutoIncrementStep = 1;
            mDt.Columns.Add(col);
            col = new DataColumn(FLD_Description, typeof(string));
            mDt.Columns.Add(col);
            col = new DataColumn(FLD_Date, typeof(DateTime));
            mDt.Columns.Add(col);
            col = new DataColumn(FLD_Price, typeof(Decimal));
            mDt.Columns.Add(col);
        }

The initialization code, I build a Datatable on the Constructor code of the form.

        private void btnCarica_Click(object sender, EventArgs e)
        {
            mDt.Rows.Clear();

            DataRow row = mDt.NewRow();
            row[FLD_Description] = "Quaderno";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 1.5;
            mDt.Rows.Add(row);

            row = mDt.NewRow();
            row[FLD_Description] = "Penna";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 2.8;
            mDt.Rows.Add(row);

            row = mDt.NewRow();
            row[FLD_Description] = "Gomma";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 0.7;
            mDt.Rows.Add(row);

            row = mDt.NewRow();
            row[FLD_Description] = "Matita";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 1.1;
            mDt.Rows.Add(row);

            row = mDt.NewRow();
            row[FLD_Description] = "Block notes";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 2.8;
            mDt.Rows.Add(row);

            row = mDt.NewRow();
            row[FLD_Description] = "Pennarelli 12 colori";
            row[FLD_Date] = DateTime.Now;
            row[FLD_Price] = 6.7;
            mDt.Rows.Add(row);

            mDt.AcceptChanges();

            Mostra();
        }

Here I build some rows, put them in the DataTable and call the Mostra method, wich shows the rows in the textbox.

        private void Mostra()
        {
            this.txtResult.Text = string.Empty;
            for( int i=0; i< mDt.Rows.Count;i++)
            {
                MostraRiga(mDt.Rows[i]);
            }
    
        }

        private void MostraRiga(DataRow pRow)
        {
            this.txtResult.Text += "ID: " + pRow[FLD_ID].ToString() + Environment.NewLine;
            this.txtResult.Text += "Description: " + pRow[FLD_Description].ToString() + Environment.NewLine;
            this.txtResult.Text += "Date: " + pRow[FLD_Date].ToString() + Environment.NewLine;
            this.txtResult.Text += "Price: " + pRow[FLD_Price].ToString() + Environment.NewLine;
            this.txtResult.Text += Environment.NewLine;
        }

This is the Mostra method and the MostraRiga Method, made to show the content of the table rows on the textbox.

        private void btnAdd_Click(object sender, EventArgs e)
        {

            DataRow row = mDt.NewRow();
            mDt.Rows.Add(row);
            row[FLD_Description] = string.Format("Nuova riga {0}", row[FLD_ID]);
            row[FLD_Date] = DateTime.Now;
            decimal pippo = Convert.ToDecimal(row[FLD_ID]);
            row[FLD_Price] = pippo*0.98m;

            mDt.AcceptChanges();

            MostraRiga(row);
        }

Here is the AddRow test, that simply builds a row, adds it to the table and then shows it on the textbox.

        private void btnDelete_Click(object sender, EventArgs e)
        {
            DataRow row = mDt.Rows[0];
            int id = Convert.ToInt32(row[FLD_ID]);
            row.Delete();
            string filter = string.Format("{0} = {1}", FLD_ID, id);
            DataView vi = new DataView(mDt, filter,"", DataViewRowState.Deleted);
            DataTable tt = vi.ToTable();
            mDt.AcceptChanges();
            MostraRiga(tt.Rows[0]);
        }

And finally the most important bit of code, the code that helps us to show the informations of the deleted row.
As you can see, the method simply deletes the first row of the DataTable, saving it’s ID.
After the deletion, to be able to get the whole row, I build a dataview that retrieves the row I’ve deleted and then uses the ToTable method of the DataView to put the data in a new Table. Then I give the Row to the MostraRiga (ShowRow) method and I can see its content on my textbox.

The ToTable passage is very important, because if you try to pass to the function something like:

MostraRiga(vi[0].Row);

Whichis perfectly legal with a non deleted row, you instead receive an Exception, because you cannot access deleted rows data.

posted @ lunedì 9 agosto 2010 17.03 | Feedback (0)

domenica 1 agosto 2010 #

How to create the ASP.NET 2.0 authentication tables on a SQL Server DB

The translation of this post is very simple, because I am not enough fluent in english to write what I wrote in italian, but I just write something to the beginners, the newbies to a new technology. Never stop in front of an obstacle, in our business we got the luck that almost everything has already been solved by someone else. So F1, or Google, or BING or a forum are always not far from you.

My problem, being a beginner in ASP.Net MVC was simple, the base template of this technology in Visual Studio, creates me a fully functional website to experiment with, but even though there is a nice Registration Form and Login Form, they don’t work, because they need that in your database you have a precise schema of tables and stored procedures to make things work.

The solution is a small utility installed by the .Net framework 2.0 in his folder.

I found this article: Creating the Membership Schema in SQL Server, (which was on the ASP.Net, the same where I can find tutorials on MVC) where it is explained not only how to build the tables using the RUN command: %WINDIR%\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe that runs a nice wizard that creates or removes the authentication tables on a SQL Server database, but it explains also how the authentication system works. After the creation of the tables and the set up of the connection string of my web application to the database, the ASP.Net MVC basic site has full registration and login functionalities.

Maybe for those who work with ASP.Net 2.0 from the beginning this thing is probably obvious and elementary. But for a beginner starting with a new technology existing from a long time, usually the first steps are the highest to climb. For me step one is done, now let’s try the step 2.

posted @ domenica 1 agosto 2010 11.07 | Feedback (0)

Copyright © Sabrina C.

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski