Passing data to ASP.NET webservice using JSON - asp.net

I have successfully returned data from a ASP.Net webservice in JSON format (using a service method that required no parameters) but have struggled with making a webservice call that requires a parameter.
Webservice:
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=True)> _
Public Function TestWebService(ByVal Description As String) As Stock
Dim res As New Stock(Guid.NewGuid, Description)
Return res
End Function
Object:
Public Class Stock
Public Sub New()
End Sub
Public Sub New(ByVal StockID As Guid, ByVal Description As String)
Me._StockID = StockID
Me._Description = Description
End Sub
Public Property StockID As Guid
Public Property Description As String
End Class
Javascript:
client = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
client.onreadystatechange = DataReturnedFromHttpRequest;
client.open("GET", "/MyWebService.asmx/TestWebService?" + JSON.stringify({"Description":["Test"]}), true);
client.setRequestHeader("Content-Type", "application/json");
client.send(null);
Response:
{
"Message": "Invalid web service call, missing value for parameter: \u0027Description\u0027.",
"StackTrace": " at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)",
"ExceptionType": "System.InvalidOperationException"
}
I understand the error but cant seem to work out how to format my request correctly.

Finally got it... So for anyone curious the answer was trival.
The get request must be in the following format
/MyWebService.asmx/MyWebserviceMethod?Param1=%22ParamValue1%22&Param2=%22ParamValue2
Then it works like a charm.

Related

Calling and serializing FB feed

I am calling FB feed from multiple FB pages with
/posts?ids=OI.Plavipingvin,217384491624554&limit=5&fields=message,created_time,id
This is the feed I get:
{
"217384491624554": {
"data": [
{
"message": "Obećanje i zavjet položeni. Dobrodošli u OI Javor ❤",
"created_time": "2017-01-08T01:05:25+0000",
"id": "217384491624554_1575515795811410"
},
{
"message": "Zimovanje u punom tijeku :-)",
"created_time": "2017-01-04T10:06:57+0000",
"id": "217384491624554_1572127976150192"
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.8/217384491624554/posts?fields=message,created_time,id&limit=2&format=json&since=1483837525&access_token=EAACEdEose0cBAMlhIYetCMo0m83Jdo3F7rk4NYmm47Q1T19UDxlKhMQnjDW4Mmelqu3vzTITnVA7E0ZBgl6jDmlHC8J7ZCX4TW2xB0xoHIySu3MK5d9yUWjqMLdUrRab9KTfH1WyzpEfIbxG7JlhPnZACfiFWFfhvO9vrAZCrAZDZD&__paging_token=enc_AdB6GEshkXkXuRJcuiHCF1aoS4rK7Myp3P6mFZAUFeZAPbRVdtmihE7UAOIlFDuTjVKHvmBeiMLmWfIZBfCER7cYrS08kccUDDoixEb2ZABASuwAigZDZD&__previous=1",
"next": "https://graph.facebook.com/v2.8/217384491624554/posts?fields=message,created_time,id&limit=2&format=json&access_token=EAACEdEose0cBAMlhIYetCMo0m83Jdo3F7rk4NYmm47Q1T19UDxlKhMQnjDW4Mmelqu3vzTITnVA7E0ZBgl6jDmlHC8J7ZCX4TW2xB0xoHIySu3MK5d9yUWjqMLdUrRab9KTfH1WyzpEfIbxG7JlhPnZACfiFWFfhvO9vrAZCrAZDZD&until=1483524417&__paging_token=enc_AdBeiIQZBem7NbobO8r183HtpPnZAOY6CRyehrr8uDJZBXkSS5kKS3YpqdmosFZCGZBobXwMnKW4hEsAIEZCjhYCAL2NdAX7ZCZAyWHZB7GhQCS0IQIqEZBwZDZD"
}
},
"OI.Plavipingvin": {
"data": [
{
"message": "Sretnu novu godinu želi vam Uprava odreda. Budite sretni i zadovoljni. I naravno - pripravni za nove avanture! 🎈 🎈 🎈",
"created_time": "2017-01-02T10:07:27+0000",
"id": "379925365427474_1274199672666701"
},
{
"message": "Jutros na Omanovcu. Imamo snijeg! :)",
"created_time": "2016-12-28T07:03:07+0000",
"id": "379925365427474_1269358063150862"
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.8/379925365427474/posts?fields=message,created_time,id&limit=2&format=json&since=1483351647&access_token=EAACEdEose0cBAMlhIYetCMo0m83Jdo3F7rk4NYmm47Q1T19UDxlKhMQnjDW4Mmelqu3vzTITnVA7E0ZBgl6jDmlHC8J7ZCX4TW2xB0xoHIySu3MK5d9yUWjqMLdUrRab9KTfH1WyzpEfIbxG7JlhPnZACfiFWFfhvO9vrAZCrAZDZD&__paging_token=enc_AdDjsccg8E9vHw7XXgXW22NDK0l3MH4mR5XvwXidebNK2Kb8bdewjPiTLGDP8yNw8rpcHYT8VME5YPxLhZC0QZCjdLkHBYJCQZBYdQQWsfmhmC2yQZDZD&__previous=1",
"next": "https://graph.facebook.com/v2.8/379925365427474/posts?fields=message,created_time,id&limit=2&format=json&access_token=EAACEdEose0cBAMlhIYetCMo0m83Jdo3F7rk4NYmm47Q1T19UDxlKhMQnjDW4Mmelqu3vzTITnVA7E0ZBgl6jDmlHC8J7ZCX4TW2xB0xoHIySu3MK5d9yUWjqMLdUrRab9KTfH1WyzpEfIbxG7JlhPnZACfiFWFfhvO9vrAZCrAZDZD&until=1482908587&__paging_token=enc_AdDZCnhwlRCxibv0aGr141JPdbcHcJssKFjhtToaTpfqKbZABvo5g0fhtCgDpwCNoMBopGK4o0CJxXzRyRJKxLCqOh0belZCXBQdTNZCEF5eRuu6agZDZD"
}
}
}
My current FBClass:
Public Class FBData
Public Property data As New List(Of FBFeed)
End Class
Public Class FBFeed
Public Property message As String
Public Property created_time As DateTime
Public Property id As String
End Class
Current GetPosts function, ordering and showing result:
Public Shared Function GetPosts( accessToken As String ) As FBData
Dim APIlink As String = "https://graph.facebook.com/posts?ids=OI.Plavipingvin,217384491624554&limit=5&fields=message,created_time,id&access_token=" & accessToken
Dim client As New WebClient()
client.Encoding = System.Text.Encoding.UTF8
Dim strJson As [String] = client.DownloadString(APIlink)
Dim result As FBData = Newtonsoft.Json.JsonConvert.DeserializeObject(Of FBData)( strJson )
Return result
End Function
Dim array1 As FBData = GetPosts ( accessToken )
For Each Msg As FBFeed In array1.data.OrderByDescending(Function(x) x.created_time)
Response.Write( i & ". " & Msg.created_time & "<br />" )
Next
What FBClass should I use for serialization of this JSON and how to read FBClass list (or array)? I don't need User-ID or data tags.
While my other answer works, it's a bit clumsy if one has a bunch of feeds to deal with, so this should be a more effective answer. I chose not to edit the previous answer because it's valid depending on one's needs.
Given this revised class structure...
Public Class FBFeed
Public Property data As Datum()
Public Property paging As Paging
End Class
Public Class Datum
Public Property message As String
Public Property created_time As DateTime
Public Property id As String
End Class
Public Class Paging
Public Property previous As String
Public Property [next] As String
End Class
...and this revised GetPosts method...
Public Shared Function GetPosts(accessToken As String, ParamArray args() As String) As Dictionary(Of String, FBFeed)
'Dim APIlink As String = "https://graph.facebook.com/posts?ids=OI.Plavipingvin,217384491624554&limit=5&fields=message,created_time,id&access_token=" & accessToken
Dim Ids As String = Join(args, ",")
Dim APITemplate As String = "https://graph.facebook.com/posts?ids={0}&limit=5&fields=message,created_time,id&access_token={1}"
Dim APIlink As String = String.Format(APITemplate, Ids, accessToken)
Using client As New WebClient()
client.Encoding = Text.Encoding.UTF8
Dim strJson As String = client.DownloadString(APIlink)
Return Newtonsoft.Json.JsonConvert.DeserializeObject(Of Dictionary(Of String, FBFeed))(strJson)
End Using
End Function
...the usage in the page request handler becomes...
Dim MyData As New List(Of Datum)
Dim IdList As New List(Of String)
IdList.Add("OI.Plavipingvin")
IdList.Add("217384491624554")
With GetPosts("Access Token Here", IdList.ToArray)
' We have a Dictionary(Of String, FBFeed) we can flatten with SelectMany
' and consolidate the Datum arrays into the MyData List(Of Datum) above
MyData.AddRange(.Values.SelectMany(Function(x) x.data).ToList())
End With
For Each Msg As Datum In MyData.OrderByDescending(Function(x) x.created_time)
Response.Write(Msg.message & ". " & Msg.created_time & "<br />")
Next
The class structure would have to look like this:
Imports Newtonsoft.Json
Public Class FBData
<JsonProperty(PropertyName:="217384491624554")>
Public Property Feed_217384491624554 As FBFeed
<JsonProperty(PropertyName:="OI.Plavipingvin")>
Public Property Feed_OIPlavipingvin As FBFeed
End Class
Public Class FBFeed
Public Property data As Datum()
Public Property paging As Paging
End Class
Public Class Datum
Public Property message As String
Public Property created_time As DateTime
Public Property id As String
End Class
Public Class Paging
Public Property previous As String
Public Property [next] As String
End Class
Update: Usage:
Dim array1 As FBData = GetPosts ( accessToken )
Dim MyData As New List(Of Datum)
MyData.AddRange(array1.Feed_217384491624554.data)
MyData.AddRange(array1.Feed_OIPlavipingvin.data)
For Each Msg As Datum In MyData.OrderByDescending(Function(x) x.created_time)
Response.Write(Msg.message & ". " & Msg.created_time & "<br />")
Next

Not getting Custom Error Message in REST

I am developing a REST API.
Below is my code:
In IService.vb
<OperationContract(),
WebGet(UriTemplate:="/DCU/{ClientID}",
RequestFormat:=WebMessageFormat.Xml,
ResponseFormat:=WebMessageFormat.Xml,
BodyStyle:=WebMessageBodyStyle.Bare)>
Function GetAllData(ByVal ClientID As String) As List(Of Data)
In Service.vb
Friend Class Service
Implements IService
Public Function GetAllData(ByVal intClientID As String) As System.Collections.Generic.List(Of Data) Implements ILightingGaleService.GetAllDCUs
Dim lstdata As New List(Of Data)()
If IsNumeric(intClientID) Then
Else
Throw New FaultException("Invalid Client ID")
End If
End Class
In Web.Config file
<serviceDebug includeExceptionDetailInFaults="true"/>
I am getting
Request Error:The server encountered an error processing the request. See server logs for more details.
When I am passing a String value in Client ID. Though I have implemented FaultExpcetion i never get "Invalid Client ID" message in POSTMAN or Web Client.
Can anyone help me on how can I get my custom message on POSTMAN or web client?
I was able to resolve this by implementing below:
I generated a class CustomError:
<DataContract> _
Public Class CustomError
Public Sub New(strError As String, strErrorDesc As String, strErrorCode As Long)
ErrorInfo = strError
ErrorDetails = strErrorDesc
ErroCode = strErrorCode
End Sub
<DataMember> _
Public Property ErrorInfo() As String
Get
Return m_ErrorInfo
End Get
Private Set(value As String)
m_ErrorInfo = value
End Set
End Property
Private m_ErrorInfo As String
<DataMember> _
Public Property ErrorDetails() As String
Get
Return m_ErrorDetails
End Get
Private Set(value As String)
m_ErrorDetails = value
End Set
End Property
Private m_ErrorDetails As String
<DataMember> _
Public Property ErroCode() As Long
Get
Return m_ErroCode
End Get
Private Set(value As Long)
m_ErroCode = value
End Set
End Property
Private m_ErroCode As Long
End Class
In Service.vb
Friend Class Service
Implements IService
Public Function GetAllData(ByVal intClientID As String) As System.Collections.Generic.List(Of Data) Implements ILightingGaleService.GetAllDCUs
Dim lstdata As New List(Of Data)()
If IsNumeric(intClientID) Then
Else
Dim ExceptionError As New CustomError("Client ID not found.", "The Client ID is not found in system.", HttpStatusCode.NotFound)
Throw New WebFaultException(Of CustomError)(ExceptionError, HttpStatusCode.NotFound)
End If
End Class
So this will generate a Webexception for my Custom Error Message which I wanted to display on my Client Application:
Now on my client application I used below
Catch ex As WebException
Dim strError = New StreamReader(ex.Response.GetResponseStream()).ReadToEnd()
lblErrorMsg.Text = strError
End Try
Hope this helps to someone.

ASP.NET Web Pages (Razor) Exit Code Block

Does anybody know how to exit a code block without interrupting page load in ASP.NET Web Page (Razor) in VB language? Let's say I have a login mechanism that execute in the following order:
Before page load:
Check if user id exist.
Check if password match.
if the user id does not exist, display error message then skip password validation and let the rest of the html page (body, footer) load. My current solution is to use VB specific GoTo.. statement which I think is ugly. Does anybody has a more elegant solution? Below is a simple sample code:
#Code
dim login As New clsLogin 'assume this class handles login validation
dim inputUserID As String 'this variable hold user id entered by user
dim inputPwd As String 'this is password entered by user
'First, check if that ID exist in database
if login.userExist(inputUserID) = false then
#<p>User does not exist !</p>
GoTo skip
End If
'If ID exist, check if password match
if login.checkPwd(inputUserID, inputPwd) = false then
#<p>Password Mismatch !</p>
GoTo skip
End If
'Passes all validation, display success message
#<p>Login Successful !</p>
skip:
End Code
I tried to replace the GoTo statement with return statement. However, it also stopped the page loading. I put the validation server code before any HTML is displayed and if I use return statement it wont show the HTML page. Any idea? Thanks in advance.
Short answer could use a function:
#Functions
function Check(byval inputUserID as integer, byval inputPwd as string) as string
dim login As New clsLogin 'assume this class handles login validation
dim result as string = string.Empty
'First, check if that ID exist in database
if login.userExist(inputUserID) = false then
return "User does not exist !"
End If
'If ID exist, check if password match
if login.checkPwd(inputUserID, inputPwd) = false then
return "Password Mismatch !"
End If
return result
end function
End functions
#Code
dim inputUserID As String 'this variable hold user id entered by user
dim inputPwd As String 'this is password entered by user
dim msg = #Check(inputUserID,inputPwd)
'Passes all validation, display success message
if string.isnullorempty(msg) then
msg = "<p>Login Successful !</p>"
end if
#msg
End Code
Hoever reading your comment seems you are looking for an elegant and sustainable solution, so I think you could approach your problem with a loosely coupled ValidationManager:
VB (translated with Telerik code converted)
Public Interface ILoginProvider
Function UserExist(inputUserID As Integer) As Boolean
Function CheckPwd(inputUserID As Integer, inputPwd As String) As Boolean
End Interface
Public Class LoginProvider
Implements ILoginProvider
Public Function UserExist(inputUserID As Integer) As Boolean
Return True
End Function
Public Function CheckPwd(inputUserID As Integer, inputPwd As String) As Boolean
Return True
End Function
End Class
Public Class ValidationResult
Public Property Result() As Boolean
Get
Return m_Result
End Get
Set
m_Result = Value
End Set
End Property
Private m_Result As Boolean
Public Property ResultMessage() As String
Get
Return m_ResultMessage
End Get
Set
m_ResultMessage = Value
End Set
End Property
Private m_ResultMessage As String
End Class
Public MustInherit Class Validator
Protected _provider As ILoginProvider
Protected _inputUserID As Integer
Protected _inputPwd As String
Public Sub New(provider As ILoginProvider, inputUserID As Integer, inputPwd As String)
_provider = provider
_inputPwd = inputPwd
_inputUserID = inputUserID
End Sub
Public MustOverride Function Validate() As ValidationResult
End Class
Public Class UserExistenceValidator
Inherits Validator
Public Sub New(provider As LoginProvider, inputUserID As Integer, inputPwd As String)
MyBase.New(provider, inputUserID, inputPwd)
End Sub
Public Overrides Function Validate() As ValidationResult
Dim result = New ValidationResult()
Dim check = _provider.UserExist(_inputUserID)
result.Result = check
If Not check Then
result.ResultMessage = "User Doesn't exist"
End If
Return result
End Function
End Class
Public Class UserPasswordValidator
Inherits Validator
Public Sub New(provider As LoginProvider, inputUserID As Integer, inputPwd As String)
MyBase.New(provider, inputUserID, inputPwd)
End Sub
Public Overrides Function Validate() As ValidationResult
Dim result = New ValidationResult()
Dim check = _provider.CheckPwd(_inputUserID, _inputPwd)
result.Result = check
If Not check Then
result.ResultMessage = "Wrong Password"
End If
Return result
End Function
End Class
Public Class ValidationManager
Private _validators As List(Of Validator)
Public Sub New()
_validators = New List(Of Validator)()
End Sub
Public Function Validate() As ValidationResult
Dim result As ValidationResult = Nothing
For Each item As var In _validators
result = item.Validate()
If Not result.Result Then
Return result
End If
Next
Return New ValidationResult() With { _
Key .Result = True, _
Key .ResultMessage = "Successfull validated" _
}
End Function
End Class
C#
public interface ILoginProvider
{
bool UserExist(int inputUserID);
bool CheckPwd(int inputUserID, string inputPwd);
}
public class LoginProvider: ILoginProvider
{
public bool UserExist(int inputUserID)
{
return true;
}
public bool CheckPwd(int inputUserID, string inputPwd)
{
return true;
}
}
public class ValidationResult
{
public bool Result { get; set; }
public string ResultMessage { get; set; }
}
public abstract class Validator
{
protected ILoginProvider _provider;
protected int _inputUserID;
protected string _inputPwd;
public Validator(ILoginProvider provider, int inputUserID, string inputPwd)
{
_provider = provider;
_inputPwd = inputPwd;
_inputUserID = inputUserID;
}
public abstract ValidationResult Validate();
}
public class UserExistenceValidator : Validator
{
public UserExistenceValidator(LoginProvider provider,int inputUserID, string inputPwd): base(provider,inputUserID, inputPwd)
{
}
public override ValidationResult Validate()
{
var result = new ValidationResult();
var check = _provider.UserExist(_inputUserID);
result.Result = check;
if(!check)
result.ResultMessage = "User Doesn't exist";
return result;
}
}
public class UserPasswordValidator : Validator
{
public UserPasswordValidator(LoginProvider provider, int inputUserID, string inputPwd)
: base(provider, inputUserID, inputPwd)
{
}
public override ValidationResult Validate()
{
var result = new ValidationResult();
var check = _provider.CheckPwd(_inputUserID, _inputPwd);
result.Result = check;
if (!check)
result.ResultMessage = "Wrong Password";
return result;
}
}
public class ValidationManager
{
List<Validator> _validators;
public ValidationManager()
{
_validators = new List<Validator>();
}
public ValidationResult Validate()
{
ValidationResult result = null;
foreach (var item in _validators)
{
result = item.Validate();
if(!result.Result)
return result;
}
return new ValidationResult(){Result = true,ResultMessage="Successfull validated" };
}
}
Use
#Function Check() As string
Dim login As New clsLogin 'assume this class handles login validation
Dim inputUserID As String 'this variable hold user id entered by user
Dim inputPwd As String 'this is password entered by user
Dim login As New LoginProvider()
Dim validators = New List(Of Validator)()
validators.Add(New UserExistenceValidator(login, 1, "test1"))
validators.Add(New UserPasswordValidator(login, 1, "test1"))
Dim manager = New ValidationManager(validators)
Dim result = manager.Validate()
return string.format("<p>{0}</p>",result.ResultMessage)
End Function
#Code
#Check()
End Code
Found it! Thx to InvernoMuto to show me how to define functions inside webpage.
First I created a class to hold login result that can provide reason if login fails.
Class LoginResult
Public Property LoginSuccess As Boolean
Public Property Reason As String
End Class
Then I created the following function for login validations
#Functions
Function CheckLogin(User As String, Pwd as String) As LoginResult
dim login As New clsLogin
Dim res as New LoginResult
res.LoginSuccess = True
if login.userExist(inputUserID) = false then
res.LoginSuccess = False
res.Reason = "User does not exist !"
return res
end if
if login.checkPwd(inputUserID, inputPwd) = false then
res.LoginSuccess = False
res.Reason = "Password mismatch !"
return res
end if
return res
End Function
End Functions
Then on the Login HTML page I just call the following code:
dim lr as LoginResult
lr = CheckLogin("someone", "password")
if lr.LoginSuccess = True then
#<p>Login Success !</p>
else
#<p>Error: #lr.Reason</p>
end if

Consume ASMX Webservice From Classic ASP Using SOAP Client 3.0

I made a webservice in VB.Net with a method returning a custom class or object.
<WebMethod()> _
Public Function CreatePerson(ByVal LastName As String, ByVal FirstName As String) As Person
Return New Person(LastName, FirstName)
End Function
Public Class Person
Public Sub New()
End Sub
Public Sub New(ByVal LastName As String, ByVal FirstName As String)
_LastName = LastName
_FirstName = FirstName
End Sub
Private _LastName As String
Public Property LastName() As String
Get
Return _LastName
End Get
Set(ByVal value As String)
_LastName = value
End Set
End Property
Private _FirstName As String
Public Property FirstName() As String
Get
Return _FirstName
End Get
Set(ByVal value As String)
_FirstName= value
End Set
End Property
End Class
I can consume it from another ASP.NET Application but the problem is when i try to consume it from Classic ASP through SOAP Client 3.0
<%
Dim Result, oSoapClient
Set oSoapClient = Server.CreateObject("MSSOAP.SoapClient30")
oSoapClient.ClientProperty("ServerHTTPRequest") = True
Call oSoapClient.mssoapinit ("http://MyServer/MyWebService/MyWebService.asmx?WSDL")
Result = oSoapClient.CreatePerson("Sassaroli", "Rinaldo")
Response.Write(Result.LastName)
%>
I get an error:
Microsoft VBScript runtime error '800a01a8'
Object required
at "Response.Write(Result.LastName)" Line.
I can see Result is a string array with no elements
I believe that the root cause of the error is the lack of a Set keyword on the line that invokes the web service method. It should look like:
Set Result = oSoapClient.CreatePerson("Sassaroli", "Rinaldo")
That will get you past your initial problem. After that you'll need to read the result object. Your subsequent line of code:
Response.Write(Result.LastName)
will most likely result in another error. That's because the result you're getting is not really a "Person" object, it's an XML representation of that object. You can verify this with the following code:
<%
Dim Result, oSoapClient
Set oSoapClient = Server.CreateObject("MSSOAP.SoapClient30")
oSoapClient.ClientProperty("ServerHTTPRequest") = True
Call oSoapClient.mssoapinit ("http://MyServer/MyWebService/MyWebService.asmx?WSDL")
Set Result = oSoapClient.CreatePerson("Sassaroli", "Rinaldo")
Response.Write( TypeName( Result ) & "<br/>" & vbCrLf )
Response.Write( Result.item(0).text )
%>
The type that will be shown by the TypeName call will be IXMLDomSelection. You can access nodes for this object through methods and properties that are documented here.
The last line of code will display the value of the LastName property.
Hope this leads you in the correct direction.

Scrambling URLS for dynamic data

What is the best method to obfuscate the urls created in Dynamic Data?
eg \Products\List.aspx?ProductId=2 could become
\Products\List.aspx?x=UHJvZHVjdElkPTI=
where "ProductId=2" is base 64 encoded to prevent casual snooping on
\Products\List.aspx?ProductId=3
\Products\List.aspx?ProductId=4
etc...?
I will probably have to inherit from an existing object and override some function
The question is which object and what function
GetActionPath of the Metamodel object seems interesting,
but how does the DynamicRoute "{table}/{Action}.aspx" play in into it...
Right now on Asp.net 1.1 site I use an custom implementation of the following code.
http://www.mvps.org/emorcillo/en/code/aspnet/qse.shtml It is HTTPModule that uses regular expression to rewrite all the querystrings and also with reflection changes the Querystring collection with decoded values.
So where is the hook to affect the change.
I have found the solution
With advice, I have implemented a Route that inherits from DynamicDataRoute.
The methods overridden were GetVirtualPath and GetRouteData.
Here is the global.asax page
routes.Add(New EncodedDynamicDataRoute("{table}/{action}.aspx") With { _
.Defaults = New RouteValueDictionary(New With {.Action = PageAction.List}), _
.Constraints = New RouteValueDictionary(New With {.Action "List|Details|Edit|Insert"}), _
.Model = model})
Here is the Encoded DynamicDataRoute.
Imports System.Web.DynamicData
Imports System.Web.Routing
''' <summary>
''' The purpose of this class to base 64 encode the querystring parameters.
''' It converts the keys to base64 encoded and back.
''' </summary>
Public Class EncodedDynamicDataRoute
Inherits DynamicDataRoute
Public Sub New(ByVal url As String)
MyBase.New(url)
End Sub
Public Overloads Overrides Function GetRouteData(ByVal httpContext As HttpContextBase) As RouteData
Dim routeData As RouteData = MyBase.GetRouteData(httpContext)
If Not (routeData Is Nothing) Then
DecodeRouteValues(routeData.Values)
End If
Return routeData
End Function
Private Sub EncodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim strOutput As New StringBuilder
Dim val As Object
For Each column As MetaColumn In table.PrimaryKeyColumns
If routeValues.TryGetValue(column.Name, val) Then
strOutput.Append(column.Name & Chr(254) & val & Chr(255))
routeValues.Remove(column.Name)
End If
Next
Dim out As String = (Convert.ToBase64String(Encoding.ASCII.GetBytes(strOutput.ToString)))
If routeValues.ContainsKey("x") Then
routeValues.Item("x") = out
Else
routeValues.Add("x", out)
End If
End Sub
Public Overloads Overrides Function GetVirtualPath(ByVal requestContext As RequestContext, ByVal values As RouteValueDictionary) As VirtualPathData
EncodeRouteValues(values)
Return MyBase.GetVirtualPath(requestContext, values)
End Function
Private Sub DecodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim enc As New System.Text.ASCIIEncoding()
Dim val As Object
If routeValues.TryGetValue("x", val) AndAlso val <> "AAA" Then
Dim strString As String = enc.GetString(Convert.FromBase64String((val)))
Dim nameValuePairs As String() = strString.Split(Chr(255))
Dim col As MetaColumn
For Each str11 In nameValuePairs
Dim vals() As String = str11.Split(Chr(254))
If table.TryGetColumn(vals(0), col) Then
routeValues.Add(val(0), col)
End If
Next
End If
End Sub
End Class
Here is how I did it:
I created 4 functions in a module:
public static string EncryptInt(int val)
public static int DecryptInt(string val)
public static string DecryptStr(string str)
public static string EncryptStr(string source)
When I wanted to create a url I did something like this:
string.Format(#"\path\file.aspx?ID={0}&name={1}",encrypt.EncryptInt(inID),encrypt.EncriptStr(inName));
When I wanted to get the results I would call the Decrypt function on retrieved param.
I used two types because it added a level of type safety to the system, but you could just use one with strings and then call int.Parse() as needed.
Does this answer your question?
For Microsoft's Dynamic Data I believe the hooks would be found in the code behind for the template pages.

Resources