Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Wednesday, 22 December 2010

List.Sort() alphabetically

I was faced with the challenge today of sorting a list of objects, where one of the properties was a string. My objects were lists of keywords, and I wanted to sort the keywords alphabetically.

I came across some example of lambda expressions, and found that rather than having to write complicated sort methods for my class, I could just do the following:

keywords.Sort((a,b) => String.Compare(a.keyword, b.keyword)):

Awesome, works a treat!

Tuesday, 17 November 2009

PHP C# WCF Rijndael

I have been working with .NET and webservices for some time, but a colleague of mine has now moved over to using WCF instead of basic webservices.

After many, many problems dealing with simple soap message exchanges, we finally got our WCF service to talk to PHP (using NuSOAP) by setting the encoding to UTF8 and the binding to type basicHttpBinding.

My next problem was why when I was encoding data using Rijndael, was the encoded data returned from WCF not being decoded by mcrypt in PHP correctly.

Eventually, after some digging around, I found a really good article at http://benvanmol.blogspot.com/2009/10/secure-communication-between-net-and.html that summises the following points:

• You need to enable padding in the .net rijndael class. This ensures any blocks are padded with 0’s to fill them. This is done with Padding.Zeros
• Specifically set Cipher Block Chaining in the .Net class.
• The Initialisation Vector (IV) needs to be 16 bytes.
• You need to specifically set the encryption to the MD5 Hash algorithm, and change this to return the 32 character hash.
• Setup base64 encoding either end.

So, from this article by Ben van Mol I was able to produce a class from his code as follows:


public class PhpRijndael
{
System.Security.Cryptography.Rijndael r = null;

public void InitializePhpRijndael(string iv, string key,int blockSize)
{
byte[] keyBytes = Encoding.ASCII.GetBytes(EncodeTo64(key));
byte[] hash = MD5.Create().ComputeHash(keyBytes);
string ret = "";
foreach (byte a in hash)
{
ret += a.ToString("x2");
}
string iv64 = EncodeTo64(iv);
byte[] ivBytes = Convert.FromBase64String(iv64);

r = System.Security.Cryptography.Rijndael.Create();

r.Padding = PaddingMode.Zeros;
r.BlockSize = blockSize;
r.Key = Encoding.ASCII.GetBytes(ret);
r.IV = ivBytes;

}

public string Decrypt(string str)
{
byte[] encryptedBytes = Convert.FromBase64String(str);
byte[] decryptedBytes = transformBytes(
r.CreateDecryptor(), encryptedBytes);

string plaintext = Encoding.ASCII.GetString(decryptedBytes);
int idx = plaintext.IndexOf("\0");
if (idx > -1)
plaintext = plaintext.Substring(0, idx);

return plaintext;
}

public string Encrypt(string plaintext)
{
byte[] plainBytes = Encoding.ASCII.GetBytes(plaintext);
byte[] encryptedBytes = transformBytes(
r.CreateEncryptor(), plainBytes);

return Convert.ToBase64String(encryptedBytes);
}

private byte[] transformBytes(ICryptoTransform transform,
byte[] plainBytes)
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream =
new CryptoStream(memStream, transform,
CryptoStreamMode.Write);
cryptStream.Write(plainBytes, 0, plainBytes.Length);
cryptStream.Close();
byte[] encryptedBytes = memStream.ToArray();
memStream.Close();

return encryptedBytes;
}

private string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

return returnValue;

}
}


In WCF I expose this in my endpoint as:

private string passPhrase = "secret";
private string initVector = "ujkrtadxcfrzpj1Bs5fpM18doZQDGYS4";
private int keySize = 256;

public string EncryptData(string value)
{

PhpRijndael r = new PhpRijndael();
r.InitializePhpRijndael(initVector, passPhrase, keySize);
string ret = "";
ret = r.Encrypt(value);
return ret;
}
public string ReturnTestData()
{
return EncryptData("Test Encrypted Data");
}

Note: Both of these are expose on the interface as OperationContracts inside the ServiceContract.

Now, in the PHP world, we need to create a page to call this, so inside a normal html form, we do the following:

if( isset($_POST['Submit']) )
{
//Show me all errors please
error_reporting(E_ALL);
ini_set('display_errors', '1');
//load nusoap
require_once('../lib/nusoap.php');
//client config to CZ
$client = new nusoap_client('http://example/Service?wsdl',true);
$client->setEndpoint("http://example/Service/EndpointName");
$client->setUseCurl(0);
//set utf-8, or else it breaks.
$client->soap_defencoding='UTF-8';
$client->setDebugLevel( 1 );
//any errors?
$err = $client->getError();
if ($err) {
echo '

Constructor error

' . $err . '
';
echo '

Debug

' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '
';
exit();
}
// This is a paramter list that can be used later, but not used at the moment
$params = array(
'value' => "666"
);
//Call dummy method for some test info
$result = $client->call('ReturnTestData',$params);
//is there a fault?
if ($client->fault) {
echo '

Fault

'; print_r($result); echo '
';
} else {
$err = $client->getError();
if ($err) {
echo '

Error

' . $err . '
';
} else {
echo '

Result

'; print_r($result); echo '
';
}
}

//decode the base sixty four encoded data returned
$bsf = base64_decode(trim($result["ReturnTestDataResult"]));

//setup auth
$key = 'secret';
$iv='ujkrtadxcfrzpj1Bs5fpM18doZQDGYS4';

//a function to configure Rijndael from the afforementioned article
function init_rijndael ($key,$iv) {
$rj = mcrypt_module_open('rijndael-256', '', 'cbc', '');
if ($rj !== FALSE)
{
$expected_key_size = mcrypt_enc_get_key_size($rj);

$key = substr(md5(base64_encode($key)), 0, $expected_key_size);

mcrypt_generic_init($rj, $key, $iv);
}
return $rj;
}
//setup Rijndael
$rj = init_rijndael($key,$iv);

//decrypt result
$decryptedResult = mdecrypt_generic($rj, $bsf);
//print out.
echo '

Result

'; echo($decryptedResult); echo '
';
}


And hey presto - finally! a working php to WCF communication in Rijndael!

Friday, 16 October 2009

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.FormatException: Invalid character

I started receiving these errors a couple of weeks ago, very randomly, and always reporting a fault with ScriptResource.axd and a strange parameter being passed as "d" as a querystring to it.

After some reading around, I eventually came across the following thread that was dicussing the issue.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=434997

The end of the thread, dated 12/10/09 states that this is a bug in IE8 that is hopefully going to be fixed soon, and that it doesn't affect the end users view of the site.

Monday, 29 June 2009

ASP.NET Ajax document.getElementById is null or not an object

This has taken me three days to figure out. For what seemed like absolutely no reason, my ajax enabled application just stopped working. I went back through all my changes to see what it could have possibly have been to make the application start throwing the javascript document.getElementById('') is null or not an object error, and specifically, why it was doing this on document.getElementById('HEAD[0]').

I eventually found a secton of html that I had commented out with html comments, and I had included in this an asp.net ajax tag.

Removing these comments fixed the problem!

Thursday, 11 June 2009

CompareValidator doesn't fire

I have an application where I am using a CompareValidator on a field that is acting as a CAPTCHA, therefore I am comparing the value that is entered.

When testing the page, I was clicking the submit button on the form, before entering any text, but when I did this, it was submitting the form! Why, when the value couldn't possibly be the same?

The reason for it is the depths of the AJAX js files:

function CompareValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
if (ValidatorTrim(value).length == 0)
return true;
var compareTo = "";
if ((typeof(val.controltocompare) != "string") ||
(typeof(document.getElementById(val.controltocompare)) == "undefined") ||
(null == document.getElementById(val.controltocompare))) {
if (typeof(val.valuetocompare) == "string") {
compareTo = val.valuetocompare;
}
}
else {
compareTo = ValidatorGetValue(val.controltocompare);
}
var operator = "Equal";
if (typeof(val.operator) == "string") {
operator = val.operator;
}
return ValidatorCompare(value, compareTo, operator, val);
}

The following line is the culprit:

if (ValidatorTrim(value).length == 0)
return true;

If the length of the information input into the box being validated is 0, i.e. nothing entered, then this validates as true. This means that if you compare something to nothing, that is valid.... stupid, but valid.

The solution to this is to add a RequiredFieldValidator as well, which then forces the length to be greater than 0, an thus makes it all work

Thursday, 4 June 2009

Compiler Error Message: CS0115: 'ASP.pagename_aspx.GetTypeHashCode()': no suitable method found to override

I came accross this problem today when converting a set of application pages into master pages.

My initial problem was that I had set CodeFile attribute of the @Page directive, rather than the CodeBehind attribute.

The second problem was that my page was inheriting from the Masterpage, rather than from System.Web.Ui.Page.

When I fixed these it worked.

It essence, if you get this error, check out what, and where your page is inheriting from.

Tuesday, 19 May 2009

CompareValidator doesn't compare numeric amounts correctly

Well at least that is what I thought today!

I had a compare validator set on two text boxes that were used to enter monetary amounts. The validator was to ensure that box B was greater than Box A.

In this scenario, it worked:

Box A = 100, Box B = 200 = Fine

But...

Box A = 500, Box B = 1000 = Invalid

Why? Because I hadn't set the TYPE attribute of the validator to CURRENCY

D'oh!

Thursday, 14 May 2009

TinyMCE UpdatePanel Javascript errors

I have spent days on this one, and it took myself and a colleague both working on it to find a solution that actually worked!

Here's the scenario.... you want to use TinyMCE, and have it working in an UpdatePanel. It sounds simple enough.

What I did was add the TinyMCE editor script, setup my tinyMCE.init() method, and hey presto, I got my editors. I set my code behind for my save button, and it fired fine when pressed, however, the editor disappeared! So, I moved my init function into the code behind, and registered it with the scriptmanager.registerclientscript method. This was fine, and when svaing my content, the editor did not disappear anymore - however, when I clicked the save button for a second time, I got a javascript error on the editor trying to access it's content.

The specific part of the javascript from tiny_mce.js was erroring on "return this.bodyElementthis.getDoc().body"

Anyway, I searched through many examples of how to solve this, including remove the editors before performing the postback, and eventually found a downloadable example that worked:

http://codeodyssey.com/archive/2007/7/18/updatepanel-tinymce-demo-with-project-zip-file

However, when I tried to use this in my application, with TinyMCE version 3.2.3, it didn't work. I copied over the version from this download, and then it seemed to fix the problem - but I lost some of the TinyMCE functionality!

Eventually, my colleague stumbled upon this absoluetly brilliant .NET extender, that handles everything for you, and allows you customise each editor independantly:

http://weblogs.asp.net/cjdevos/archive/2008/06/19/ajax-extender-for-tinymce-continued.aspx

So, if your having problems with TinyMCE and updatepanels - download it and use it!

Wednesday, 10 December 2008

ScriptResource.axd - if(!a._events) error

I was getting this error today, for some unknown reason, and obviously debugging it is of no use, as the brightspark that declared everything as "a", "b" or "c" obviously didn't want us to!

Anyway, after some searching around on my page, I found that a modalpopupextender that I have added to my page, had an invalidad cancelcontrolid, I had mis-spelled it, and therefore this error must be because "a" in this instance was the control that was to be used to close (cancel) the popup.

The joys of using other peoples code....

Monday, 20 October 2008

AJAX NumericUpDown extender hides textbox

I couldn't for the life of me figure out why my nicely styled textbox was being hidden when I added an numeric up down extender to it.

The reason, you have to explicitly add a width attribute to the extender so that it knows how big the parent box is!

Friday, 19 September 2008

Comparing two files, one on a hard drive, and one from a web site

In my quest to create an effective and lean search engine service for the company I work for, I used to crawl all of our websites and download every file from them, and write them to a local cache. When the cache was detected as updated, my indexing system (based on Lucene.Net) detects the changes, and reindexes those sites.

You may well be able to imagine, that with over 800 sites, this is an awfully large amount of data to writing to the cache, and then an even bigger job for the index to reindex all these files!

So, what I wanted was a mechanism whereby I could compare the local copy, to a streamed copy of the file from the server into the local memory, and see there were any changes.

To do this, I immediate thought of looking for something like a checksum check, but a colleague recommended looking at doing a MD5 hash on them, using a tool like CipherLite by Obivex. Looking into this, i found an easier way, by using a webrespone to download a memory stream, opening the local file using a filestream, and performing hash on them to see whether the contents were the same:

//get a memory stream to hold the data that is downloaded
MemoryStream msFile = new MemoryStream();
writer = new BinaryWriter(msFile);
byte[] RecvBuffer = new byte[10240];
int nBytes, nTotalBytes = 0;
// loop to receive response buffer
while((nBytes = response.socket.Receive(RecvBuffer, 0, 10240, SocketFlags.None)) > 0)
{
// increment total received bytes
nTotalBytes += nBytes;
// write received buffer to file
writer.Write(RecvBuffer, 0, nBytes);
// check if the uri type not binary to can be parsed for refs
if(bParse == true)
// add received buffer to response string
strResponse += Encoding.ASCII.GetString(RecvBuffer, 0, nBytes);
// update view text
// check if connection Keep-Alive to can break the loop if response completed
if(response.KeepAlive && nTotalBytes >= response.ContentLength && response.ContentLength > 0)
break;
}
bool bContinue = false;
FileStream fStream = null;
try
{
//check to see if the file exists on the local file system
if(File.Exists(PathName))
{
//open the file, and read in the stream
fStream = File.Open(PathName, FileMode.Open,FileAccess.Read,FileShare.Read);

//compare the two streams, to see if they are the same (see later)
bContinue = compareFiles(msFile,fStream);
}
else
{
//file doesn't exist, download anyway
bContinue = true;
}
}
catch(Exception ex)
{
bContinue = true;
LogError(ex.Message,"");
}
finally
{
if(fStream!=null)
fStream.Close();
fStream = null;
}
if(bContinue)
{
//create a stream to create the new file
streamOut = File.Open(PathName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
//create the new copy
msFile.WriteTo(streamOut);
//close up
streamOut.Close();
}
msFile.Close();


So, to how the streams are compared. I adapted my solution to one I found via a google search on hashing:

bool compareFiles(MemoryStream file1, FileStream file2)
{
using (HashAlgorithm hashAlg = HashAlgorithm.Create())
{
// Calculate the hash for the files.
byte[] hashBytesA = hashAlg.ComputeHash(file1);
byte[] hashBytesB = hashAlg.ComputeHash(file2);
// Compare the hashes.
if (BitConverter.ToString(hashBytesA) == BitConverter.ToString(hashBytesB))
{
//they are the same
return true;
}
else
{
//they are different
return false;
}
}
}

Hope this helps.

Detecting an enter key press on an asp.net form (but when using AJAX as well!)

I've been more than familiar with detecting key presses in javascript for quite some time, and used to do it all the time in classic asp, but this time when I came to do it in the .net world, in was a little more involved.

This setup was also the first time I had to cope with Masterpages using AJAX inside them.

So, I have a simple content placeholder, inside this a textbox and these themselves are inside an updatepanel. I also have a modalpopup extender that shows whenever the page causes an update (asyncpostback).

So, to get this to work, I had to tie up my javascript with the ScriptManager.RegisterClientScriptBlock() method and placing the script into a LiteralControl that I had to place on the form also:

if(!Page.IsPostBack)
{
this.textBoxQuery.Attributes.Add("onkeypress", "javascript:return checkEnter(event);");
Page.RegisterHiddenField("__EVENTTARGET", textBoxQuery.ClientID);
string strScript = "function checkEnter(e){ " +
"var characterCode; " +
"if(e && e.which){ " +
"e = e; " +
"characterCode = e.which; " +
"} " +
"else { " +
"e = event; " +
"characterCode = e.keyCode; " +
"} " +
"if (characterCode == 13) " +
"{ " +
" " +
" document.getElementById('" + ButtonSearch.UniqueID + "').click(); " +
" return false; " +
"} " +
"else " +
"{ " +
" return true; " +
"}" +
"}";

ScriptManager.RegisterClientScriptBlock(LitScript, this.GetType(), "regScripts", strScript, true);
}

This now captures the enter key, and handles it as a normal button click event.

Thursday, 11 September 2008

Error messages "There is an error in XML document (1, 1994)." or inner exception of "DataTable does not match to any DataTable in source."

Today I have spent nearly 5 hours trying to get to the bottom of why I was receiving these errors.

The first error made me think that this was caused by an invalid character in my data, which was being returned from a webservice to my data in my program.

I took a copy of what was being returned using "fiddler" to see what was going on in my browser - it showed the xml being returned was fine. I even validated the XML to check.

The interesting thing was the inner exception of "DataTable does not match to any DataTable in source." thrown in Visual Studio. Looking at this, it was telling me that the datatable being returned from the webservice, was not the same as the datatable I had in Visual Studio. The strange this was, they were both typed datatables! so how could they be wrong.... well, they weren't.

The source of the problem was the following which was at position 1994 in the XML:

"diffgr:diffgram msdata="urn:schemas-microsoft-com:xml-msdata" "

This was telling me that there was a difference in the schema of the dataset... <- Note here, a difference in the DATASET. I was not returning a dataset, I was returning a datatable! Anyway, a quick google brought up a nice little link from the good boys at Microsoft:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105642

It turns out, you can't return a datatable from a webservice, you have to return a DATASET. What a load of pants.

So, to solve this, I had to alter the webservice method to return a fake dataset, that contained the datatable that I wanted, e.g:

[WebMethod]
public MyTypedDataSet(string someparams)
{
MyTypedDataSet ds = new MyTypedDataSet();
MyTypedDataTable dt = aFunctionThatGetsTheData(someparams);

ds.Tables.Add(dt.Copy());
return ds;
}
private MyTypedDataSet.MyTypedDataTable(string someinfo)
{
MyTypedDataSet.MyTypedDataTable dt;
//The work that gets the data is here
return dt;
}

I hope this helps someone if they have the same problem too!!!

Jamie.

Monday, 8 September 2008

IsNumeric in C#

IsNumeric doesn't exist in c#, it's VB specific, but i've found to work today is the following:

int result;
Int32.TryParse(value_to_try, out result);

If it can parse an Int, it returns the value to the result variable, if it fails, it returns 0.

Brilliant!

Tuesday, 29 July 2008

Regex to find images in HTML

The other day I wanted to find a way to extract the image urls from some HTML, so I found the following to work quite nicely:


Regex rgxFiles = new Regex(@"[\w/:.]+\.(?:jpg|bmp|gif|png)");
MatchCollection mtcFiles = Regex.Matches(strSourceString,@"[\w/:.]+\.(?:jpg|bmp|gif|png)",RegexOptions.IgnoreCase);

foreach (Match mFile in mtcFiles)
{

//mFile.Value will contain the image address that we can work with

}

The HTTP verb POST used to access path ''Path' is not allowed

This is probably one of the most stupid mistakes I have made in months. I kept this message when transferring data from one website page to another, and I couldn't understand why.....


Hmmmm.....


It helped when I gave the webpage an aspx extension!!!


One problem here, if you try and post data to a page that is not asp or aspx, IIS and .NET does NOT like it!

Hope this helps!

Thursday, 24 July 2008

REGEX to remove HTML formatting

I've seen a few ways of using Regex to remove HTML formatting, but the following seems to work fine for me!:

public string Strip(string text)
{
string sReturn = System.Text.RegularExpressions.Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
sReturn = System.Text.RegularExpressions.Regex.Replace(text, @"(&\w*;)", string.Empty);
return sReturn;
}

Friday, 11 July 2008

ModalPopupExtender for deleting DataGridView rows

In the words of Little Britain, "What a caffuffle"!

How difficult does it have to be to delete a row from a datagrid, and use an AJAX ModalPopupExtender to provide a nice UI for it? The answer, very!

For all those who are trying to do it, i'm not going to re-invent the wheel, simply take yourself over to Matt Berseths' blog, where he has managed to do it (and now have I!)

http://mattberseth.com/blog/2007/07/confirm_gridview_deletes_with.html

Thursday, 10 July 2008

Chaning the ASP.NET Name attribute

This had be frustrated for days - you can change the ID property of a dynamically created control, but you can't change the NAME attribute!

Why do I care? Simple, I wanted to use the ID property for use in JavaScript calls, and the NAME attribute for when I was posting the form data - for example, I wanted two textboxes, one with an ID of 12, but a name of "Name", and another with an ID of 13, but a name of "Age", so that when I submitted the form data, I could get a friendly name for it.

(Before anyone harps on about "the .NET framework uses the NAME property in postbacks" - I do know this, but it is not required in this scenario.)

So, how did I do it? I created a class that inherits from TextBox, and then created an property within it called Name. I then overrided the render method to render the box as I needed it to be done in HTML:


public class MTextBox : TextBox
{
private string _mName;
public string Name
{
get { return _mName; }
set { _mName = value; }
}
//overriden to print name attribute correctly
protected override void Render(HtmlTextWriter writer)
{
string sOutput = "";
//Here you can squirt out your HTML in whatever format you want, e.g. you can
//squirt out the HTML of Name=\" + __mName + "\" etc
writer.Write(sOutput);
}
}


Sorry I can't give a more complete example, but blogger treats the code sample as HTML!!! Contact me if you want the code.

In my application, I can then just do this:

MTextBox textBox = new MTextBox();
textBox.Name = "Something I want it to be!!!";

Wednesday, 14 May 2008

FileInfo FullName returns case insensitive results

I had a problem the other day whereby I was trying to record urls that contained encoded information as a querystring parameter, e.g. file.asp?param=4H4tTy7u

The problem was that even though I could see the files in case sensitive manner, when I saved the file to the filesystem, they were being read as case insensitive, e.g. file.asp?param=4h4tty7u

This caused major problems, as when I then unencoded the information in the querystring, I was getting completely the wrong information.

Upon tracing, it became apparent that although I could see the mixed cases in windows explorer, the underlying filesystem was case insensitive, and returned all results in lowercase - something which was causing the major problem.

To get round this, I first found an MS article that said it was caused by a .NET 2 framework bug from 2006 that set a registry value to indicate case insensitivity to the filesystem. After I changed this value and restarted, still it did not work.

After a bit of googling, I found the following article, which proved to solve the problem for me eventually - quite why such an elaborate solution is required is beyond me, but hey! of you have the same problem, at least here is the solution!


//within your code....
string sFileToProcess = fi.FullName;

string dir = Path.GetDirectoryName(sFileToProcess);
dir = ReplaceDirsWithExactCase(
dir,
Path.GetPathRoot(dir).ToUpper());
string filename =
Path.GetFileName(GetExactCaseForFilename(sFileToProcess));
Console.WriteLine(dir + "\\" + filename);



//methods needed for the above to work.
public static string ReplaceDirsWithExactCase(string fullpath, string parent)
{
if (fullpath.LastIndexOf(@"\") != fullpath.Length - 1)
fullpath += @"\";
if (parent.LastIndexOf(@"\") != parent.Length - 1)
parent += @"\";
string lookfor =
fullpath.ToLower().Replace(parent.ToLower(), "");
lookfor =
(parent + lookfor.Substring(0,
lookfor.IndexOf(@"\"))).ToLower();
string[] dirs =
Directory.GetDirectories(parent);
foreach (string dir in dirs)
if (dir.ToLower() == lookfor)
{
if (lookfor + @"\" == fullpath.ToLower())
return dir;
else
return ReplaceDirsWithExactCase(fullpath, dir);
}
return null;
}


public static string GetExactCaseForFilename(string file)
{
string[] files =
Directory.GetFiles(Path.GetDirectoryName(file));
foreach (string f in files)
if (f.ToLower() == file.ToLower())
return f;
return null;
}