I have been banging my head against a wall all day and am starting to think this isnt possible so you guys are my last hope!
I have a user control which is used to create messages and then allows the message to be emailed or sent via SMS depending on what aspx page the user control is on. I have a fair amount of logic in the user control and was find I was doing alot of this:
If type="email" Then
'Logic for email
Exit Sub
End If
If type="sms" Then
'Logic for sms
Exit Sub
End If
And alot of the logic was similar so there was alot of duplication. I ended up abstracting out the similar logic for email and SMS into an Interface:
Public Interface IContactMessager(Of T)
Sub Delete(ref As String)
Function GetAll() As List(Of T)
Function GetByRef(ref As String) As T
Function MessageExists(ref As String) As Boolean
ReadOnly Property RefField() As String
Sub Save(ref As String, message As String)
Sub SendMessage(contact As String, message As String)
Sub Update(ref As String, message As String)
End Interface
I now have a sms and email manager classes that inherit from this interface. This should allow me to do something similar to the below in the user control
Dim handler As IContactMessager(Of Email)=if(type="sms",SMSHandler,EmailHandler)
Then instead of ifs I can just do handler.logic and it will run the correct logic.
Now heres my issue, and its due to the interface being generic. Ideally id like to do the following:
Public ReadOnly Property ContactMessagerHandler() As IContactMessager(Of T)
Get
Return If(MessageType.ToLower() = "email", New EmailContactMessager(), New SMSContactMessager())
End Get
End Property
However I cant have the (Of T) because obviously it has no idea what type to make this. I need to somehow dynamically set this type but I have run out of ideas.
A few things i have toyed with:
Trying to see if I can pass an the object from the calling aspx page
Making the interface a basepage instead then making the calling aspx page inherit from the base page and then trying to get the type from the usercontrols parent, but to no success
Attempting to make methods to set the type of the interface based on text passed through from the calling aspx page
None of these work. Does anyone else have any other ideas? Hopefully this makes sense, if not let me know if I can improve the question somehow
Related
I have some Ajax on a web page that feeds some data to a server-side VB.Net method. Once that data is in the server-side method, I need to call another server-side method to use the data I just collected. Here is a really simplified example:
' This method gets the input from the Ajax code on the web page.
<System.Web.Services.WebMethod> _
Public Shared Sub GetAwesome(VBInputText As String)
Dim strTest As String = VBInputText
' Now that we have collected input from the user,
' we need to run a method that does a ton of other stuff.
DisplayAwesome(VBInputText)
End Sub
Protected Sub DisplayAwesome(AwesomeIn As String)
' The real app does a lot more than this. For this example, it
' just sets the text of a literal.
litAwesomeResult.Text = AwesomeIn
End Sub
Of course, in the above example DisplayAwesome(VBInputText) gives me the 'Cannot refer to an instance member...' error. So, is it possible now to call Protected Sub DisplayAwesome from Public Shared Sub GetAwesome? I'm hoping to stay close to this sort of solution because it would play very well with the app as it is already written by another coworker.
unfortunately you cannot do this, Since the page method DisplayAwesome is defined as Protected and you requires an instance of the class to access the Protected method. But changes in another instance will not reflect in the current UI. another thing you can do is Make DisplayAwesome as Shared, but this time you cannot access the UI elements inside the shared function.
The thing you can do in this situation is, return data to the called method(in front end) and handle the litAwesomeResult.Text there
Call sub with name of Form Class like this:
FormName.DisplayAwesome(VBInputText)
In VB.Net, you can call the method not shared from a shared method with Name of Form Class by default instance, because The default instance is an object Form type that the VB application framework create and manage it, when the form is added to the project.
For more info see this :
VB.NET Default Form Instances
I have some web pages that include other pages, and I need to check if a variable (a string) has been declared in the page or not.
I was exploring try catch and finally, but im always getting a compiler error saying the variable doesnt exits.
syntax in my head is:
if variable(exists) then
do something
else
do nothing
end if
From what im finding is this wont even compile if the variable wasnt defined anywhere. I kinda knew that, I was just hoping to find some kind of work around. :/
The only way I know of is to use reflection...
This will not work for variables defined within subs/functions...
Friend Function VariableExists(ByVal variableName As String) As Boolean
For Each tField As FieldInfo In Me.GetType.GetFields
If tField.Name.ToLower() = variableName.ToLower() Then
Return True
End If
Next
Return False
End Function
Cose here is untested and may contain minor errors. Think of it more like pseudocode.
Instead of declaring a variable, how about adding a simple Interface that you can use in the pages that need to be processed a specific way, then you can test whether or not the page implements the Interface?
For example:
Public Interface IMySpecialInterface
End Interface
In the pages that you want special behavior for:
Public Page MySpecialPage
Implements IMySpecialInterface
End Page
In the code that processes the pages:
If TypeOf Me.Page Is IMySpecialInterface Then
What about using an interface:
Public Interface ISpecialProp
Property SpecialProp() As String
End Interface
Then you can test, if a class implements the interface or not using this code:
Dim spec = TryCast(obj, ISpecialProp)
If spec IsNot Nothing Then
Console.WriteLine(spec.SpecialProp)
End If
I am tracking down a bug in some old aspx code. The problem is that one some very rare occations (1/10.000 pageviews or so) two users are mixed up, ie. user A sees user B data.
Here is how the code is structured: We have a user class which is defined in a module like this:
Public Module MyGlobals
Public myUser As CMyUser
End Module
On the loginpage, we validate the username/password and if valid then the coorosponding userid is loaded from db, and we do:
FormsAuthentication.SetAuthCookie(userid, False)
Then we redirect to the secure area. In the secure areas MasterPage, on event Page_Init, we then have:
If Context.User.Identity.IsAuthenticated then
' Initialize the user class (user data is loaded)
MyGlobals.myUser = New CMyUser(Context.User.Identity.Name)
Else
' Redirect to loginpage
End If
Hereafter, is it safe to access the
MyGlobals.myUser
instance from every page which has the secure masterpage as masterpage, or could there be issues with this structure?
A VB.Net Module is like a static class with a private constructor and only static fields in C#.
That means, all variables declared in a module are shared across all threads. Hence every request(User) that's using this module will overwrite the old value.
I would strongly recommend to use Session to store user-sensitive data.
But i'm not sure why you want to store the Username because it's already stored when using FormsAuthentication(as you've shown yourself above).
If you really need this wrapper, you could easily achieve it even in a static context via HttpContext.Current.Session:
Module MyGlobals
Public Property myUser As CMyUser
Get
If HttpContext.Current.Session("CurrentUser") Is Nothing Then
Return Nothing
Else
Return DirectCast(HttpContext.Current.Session("CurrentUser"), CMyUser)
End If
End Get
Set(ByVal value As CMyUser)
HttpContext.Current.Session("CurrentUser") = value
End Set
End Property
End Module
In ASP.Net, is it possible to pass parameters to the "New" constructor of a User Control class? In VB.Net:
Public Sub New(ByVal pRequiredParam As String)
'Do something with required Param
End Sub
When I use this user control in a generic ASP.Net page, it doesn't prompt me for "pRequiredParam". Of course, if this was a "normal" class, I would have to supply "pRequiredParam" when I instantiate the object. Is this not possible with a User Control?
While you can certainly create a custom constructor like the one you show in your code sample, you cannot force the designer to make use of it. How would it determine what to send as argument to the constructor?
However, you can load the control dynamically in your code-behind file, and then use whatever parameters it defines. Note though that if you want the control to also work well with the graphical designer, I think that the control need to have a public constructor that takes no parameters (but I think you get that automatically in VB.NET?)
What's the best way to view the data that LoadPostData event is loading to the controls in ASP.NET?
It's actually really simple. The NameValueCollection that get's passed to this method of EVERY control that implements the IPostbackDataHandler interface is the contents of Page.Request.Form. So you can access it at any time by getting a Watch on HttpContext.Current.Request.Form.
Ugh... I would suggest setting your IDE environment up to debug the .net framework, and set a breakpoint on the LoadPostData() method of Control. That's a bit heavy-handed, but if you're willing to wade through the recursive calls to the Control class (perhaps set a conditional breakpoint on the method?), you will be able to get to the data that way.
Good luck!
If you want to be sure you're looking at the data going into a particular control, you can subclass its control type and break during a custom implementation of IPostBackDataHandler.LoadPostData.
For example, you have a programmatically added control to collect the user's city. Change:
Public City As Textbox
to
Public City As BreakableLoadPostDataTextBox
Public Class BreakableLoadPostDataTextBox
Inherits TextBox
Protected Overrides Function LoadPostData( _
ByVal postDataKey As String, _
ByVal postCollection As System.Collections.Specialized.NameValueCollection) _
As Boolean
Return MyBase.LoadPostData(postDataKey, postCollection) ' Break here
End Function
End Class
Set a breakpoint on the Return call. When execution breaks, you should be able to see the postDataKey that's being used to read the control's new value out of the postCollection. You can of course augment this method to your heart's content with Trace calls and whatnot.