thriftthreads.com

12/16/2013

thriftthreads.com

The VB.NET Guru created the search engine for this site, pretty spiffy if you ask me.  I’ll blog about it later, it passes an array of search terms into the sql server which is pretty clever I like to think. And it does have amazing deals and super cheap pricing on quality used clothing, especially jeans.


Datagrid not updating in an UpdatePanel

11/29/2013

Here’s a fun bug I ran into today.  I had a datagrid that had a delete command in one of the columns.  The code worked find but the datagrid was not updating on the screen when a row was removed.  If you hit refresh after the command you would see that the update happened correctly.

The fix was very simple, but hard to figure out.  I had to create an empty function for the delete command in the pages code behind.  apparently Ajax was trying to fire the function which didn’t exist and crashing.

For the delete command I added the following function that fixed the issue, you may need to add others if your cashing on commands other then delete:

Private Sub GridView1_RowDeleting(sender As Object, e As GridViewDeleteEventArgs) Handles GridView1.RowDeleting
 'Empty Method Needed So Ajax doesn't die...
End Sub

Set Focus On a textbox without highlighting the text

10/24/2013

Ever have the need to set focus on a text box in your code behind, but you want the cursor at the end of the text so that the user can keep typing?  I have read a number of blog posts and discussion boards on this topic to be horrified to find that there was no simple solution. But your in luck I found one post online that almost had the solution, and then with a little bit of tweaking I was able to create my own simple solution.  This should work on any web browser.

I added the following property to my “<asp:textbox>”:

onfocus="tmpStr = this.value;this.value='';this.value=tmpStr;" 

This little gem grabs the text from the box, clears it out, and then re-enters it.  This gets rid of the text highlight that ASP.NET will create for you.  It’s pretty sweet. Solved a huge problem for me with my auto complete control.


Signing a Amazon Product Advertising API Request

09/28/2013

I’ve been looking around the web and I haven’t found any good examples of how to make an Amazon Product Advertising API Request in VB.NET.  There are a few out there in C# and amazon has some terrible C# sample code.  How would you like to just use amazon’s good old WSDL in visual studio? Well here’s how to do it!

I got the source code to this from:
http://flyingpies.wordpress.com/2009/08/13/signing-amazon-product-advertising-api-cwcf-part-2/ 

I converted it to VB.NET and lumped it into one Class file (AmazonSignature.vb):


Imports System.Security.Cryptography
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Dispatcher
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.ServiceModel.Description
Imports System.Xml

Namespace AmazonSignature
 Public Class AmazonSigningMessageInspector
 Implements IClientMessageInspector
 Private accessKeyId As String = ""
 Private secretKey As String = ""

Public Sub New(accessKeyId As String, secretKey As String)
 Me.accessKeyId = accessKeyId
 Me.secretKey = secretKey
 End Sub

Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
 ' prepare the data to sign
 Dim operation As String = Regex.Match(request.Headers.Action, "[^/]+$").ToString()
 Dim now As DateTime = DateTime.UtcNow
 Dim timestamp As String = now.ToString("yyyy-MM-ddTHH:mm:ssZ")
 Dim signMe As String = operation & timestamp
 Dim bytesToSign As Byte() = Encoding.UTF8.GetBytes(signMe)

' sign the data
 Dim secretKeyBytes As Byte() = Encoding.UTF8.GetBytes(secretKey)
 Dim hmacSha256 As HMAC = New HMACSHA256(secretKeyBytes)
 Dim hashBytes As Byte() = hmacSha256.ComputeHash(bytesToSign)
 Dim signature As String = Convert.ToBase64String(hashBytes)

' add the signature information to the request headers
 request.Headers.Add(New AmazonHeader("AWSAccessKeyId", accessKeyId))
 request.Headers.Add(New AmazonHeader("Timestamp", timestamp))
 request.Headers.Add(New AmazonHeader("Signature", signature))

Return Nothing
 End Function

Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply
 End Sub
 End Class

Public Class AmazonSigningEndpointBehavior
 Implements IEndpointBehavior
 Private accessKeyId As String = ""
 Private secretKey As String = ""

Public Sub New(accessKeyId As String, secretKey As String)
 Me.accessKeyId = accessKeyId
 Me.secretKey = secretKey
 End Sub

Public Sub ApplyClientBehavior(serviceEndpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
 clientRuntime.MessageInspectors.Add(New AmazonSigningMessageInspector(accessKeyId, secretKey))
 End Sub

Public Sub ApplyDispatchBehavior(serviceEndpoint As ServiceEndpoint, endpointDispatcher As EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior
 Return
 End Sub
 Public Sub Validate(serviceEndpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate
 Return
 End Sub
 Public Sub AddBindingParameters(serviceEndpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters
 Return
 End Sub
 End Class

Public Class AmazonHeader
 Inherits MessageHeader
 Private m_name As String
 Private value As String

Public Sub New(name As String, value As String)
 Me.m_name = name
 Me.value = value
 End Sub

Public Overrides ReadOnly Property Name() As String
 Get
 Return m_name
 End Get
 End Property
 Public Overrides ReadOnly Property [Namespace]() As String
 Get
 Return "http://security.amazonaws.com/doc/2007-01-01/"
 End Get
 End Property

Protected Overrides Sub OnWriteHeaderContents(xmlDictionaryWriter As XmlDictionaryWriter, messageVersion As MessageVersion)
 xmlDictionaryWriter.WriteString(value)
 End Sub
 End Class

End Namespace

Now just add this handy dandy line of code to your otherwise regular SOAP request:


(AWSECommerceServicePortTypeClient).ChannelFactory.Endpoint.EndpointBehaviors.Add(New AmazonSignature.AmazonSigningEndpointBehavior("..AWSAccessKeyId...", "...AWS Secret Key.."))

And BAM! you just singed your request! Pretty sweet.  Here is an ItemLookup request example:

Dim ItemReq As AmazonWS.ItemLookupRequest = New AmazonWS.ItemLookupRequest

ItemReq.IdType = AmazonWS.ItemLookupRequestIdType.ASIN
ItemReq.ResponseGroup = {"Large"}
ItemReq.IdTypeSpecified = True
ItemReq.ItemId = {"0440245923"}
Dim iL As AmazonWS.ItemLookup = New AmazonWS.ItemLookup

iL.AssociateTag = "...-20"
iL.AWSAccessKeyId = "..."

iL.Request = {ItemReq}

Dim Amzwc As AmazonWS.AWSECommerceServicePortTypeClient = New AmazonWS.AWSECommerceServicePortTypeClient()

Amzwc.ChannelFactory.Endpoint.EndpointBehaviors.Add(New AmazonSigningEndpointBehavior("..AWSAccessKeyId..", "..AWS Secret key.."))

Dim iLR As AmazonWS.ItemLookupResponse = Amzwc.ItemLookup(iL)


Sharing DataContracts between WCF Services

08/26/2013

So Say you’ve created Two separate web services, but the both share a common object. Now lets say you want to get a new copy of the object from one service, and then pass it back into the other service.  You likely will run into this gem of an error:

Value of Type … cannot be converted to …

In the past I created a Serialization routine that converted the objects back and forth, but I have discovered an even simpler way.  Now this only works if you wrote the both of the web services. There are ways to do it without them being your own,  but I will only address your own WCF services here.

Take your common objects and place them in their own Class, I like to use the ‘Common’ Namespace for this. so say:

vbguru.Common.Person

Place your common objects here in their own library  and reference the dll’s.

Now on your client software before you add a reference to the web service first add a reference to  that same dll (vbguru.common.Person) so both your web service and your client software are using the same dll.

Now add a reference to your web service (“Add Service Reference”) but before you click ok select the “Advanced…” Button. Check the box for “Reuse types in referenced assemblies” and in that list you should find a check box for “vbguru.Common” (or your library object)  Now do the same for your second web service reference.

Vola!  Both of your web services will now use the same objects!


eBay API getUserCases

08/11/2013

So I seem to have found a bug in eBay’s API, if you want to look up a buyer protection case with the method “getUserCases” you will be out of luck if you try and use a SOAP call directly to the web service, as ebay seems to have forgotten to include the ability to pass your credentials. It’s also not included in the .net SDK. So if you want to use it, you have to create a ‘raw’ web request. Good news is that it’s pretty simple if you know what you are doing, If you don’t then that’s probably why you are reading this post.

Here is my code, you need to add your own token.

Public Function GetUserCases() as String

Dim ur As System.Uri = New System.Uri("https://svcs.ebay.com/services/resolution/v1/ResolutionCaseManagementService")

Dim wc As Net.HttpWebRequest = Net.HttpWebRequest.Create(ur)

wc.Headers.Add("X-EBAY-SOA-SERVICE-NAME", "ResolutionCaseManagementService")
wc.Headers.Add("X-EBAY-SOA-OPERATION-NAME", "getUserCases")
wc.Headers.Add("X-EBAY-SOA-SERVICE-VERSION", "1.0.0")
wc.Headers.Add("X-EBAY-SOA-GLOBAL-ID", "EBAY-US")
wc.Headers.Add("X-EBAY-SOA-SECURITY-TOKEN", "...")
wc.Method = "POST"

Dim b() As Byte = System.Text.Encoding.UTF8.GetBytes(xmlString)
wc.ContentLength = b.Length
Dim rs As IO.Stream = wc.GetRequestStream

rs.Write(b, 0, b.Length)

rs.Close()

Dim wr As Net.WebResponse = wc.GetResponse()

Dim resStream As IO.Stream = wr.GetResponseStream()

Dim sr As IO.StreamReader = New IO.StreamReader(resStream)

Dim strRes As String = sr.ReadToEnd

sr.Close()
resStream.Close()
wr.Close()

Return strRes

End Function

  Private Function xmlString() As String
    Dim sw As System.Text.StringBuilder = New System.Text.StringBuilder

    sw.AppendLine("<?xml version=""1.0"" encoding=""utf-8""?>")
    sw.AppendLine("<getUserCasesRequest xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"" xmlns:ser=""http://www.ebay.com/marketplace/resolution/v1/services"">")
    sw.AppendLine("</getUserCasesRequest>")

    Return sw.ToString
  End Function


Source Control

03/09/2013

I thought I’d mention how I handle source control.  There are many options out there, but many of them are expensive, and the free ones are usually more complicated then they are worth.  Now I do miss the day of Visual Source Safe, but it had a number of issues as well.  You can use team foundation services, which I think is really cool, but I’ve never used it as it’s too expensive.

First why do I use a source control tool? Isn’t it just for software teams?  No! I use source control for all my projects.  I have a laptop, desktop, and now a windows surface pro tablet.  I have my code all set up in my source control system, and I write code on my desktop, then switch over to my laptop, and now I even work on my code on my surface pro tablet.   By using source control I can have a current copy of my code on all of my devices.

So What do I use? Guess what it’s all totally free, and integrates perfectly with visual studio’s UI. None of this command line insanity. So I mix and match two different projects.  First I use VisualSVN for my server. http://www.visualsvn.com/ They have a free edition that works great for small teams or like me just one person. And yeah you get all the power of SVN, and it installs on a windows box. (Ahh no need for some open source OS.)

Then I install an open source project for the UI integration, ankhsvn. http://ankhsvn.open.collab.net/

Ankhsvn is a great SVN client for visual studio. Using these two tools gives you a free, solid system for your source code.


Follow

Get every new post delivered to your Inbox.