Shared Functions in VB.Net - asp.net

I have to send emails when a person receives a personal message on my website and for that I use a StringBuilder to create the HTML markup of the email.
also since it is required at many other places as well I have made a Shared Function (I am using VB.NET). now my only concern is that since shared functions are shared among all objects and maybe asp.net sessions, can it be possible that before one person email is being formed and another person access the same function, it would cause the data in the stringbuilder to be overwritten..
Currently my site doesn't have many users but can this become an issue in the future... Please advise me on this... Is there any better way or standard procedure to follow when using shared functions?
Also at one time I made the mistake of using a shared connection object and it would cause close if many people were to access it.

Shared functions can only access static/global variables as well as variable inside the function scope. So, if the the function is working with any number of static/shared resources then you need to synchronize between the calls to the function.
In your case, however, it doesn't sound like you're working with any shared resources, so it shouldn't be a problem.
Here's a case that illustrates the problem:
private static myCounter As Integer = 0
public shared function IncreaseCount() As Integer
myCounter += 1
for i as integer = 0 to 10 million
//'do extensive work
next
return myCounter
End Function
Imagine that you call the function for the first time, and you would expect it to return the number 1. But due to the fact that the function was called again before the first function call got to return the counter was increased once more, which means that both function calls return 2 instead of respectively 1 and 2. All the problem arrives when you want several things working on the same static resource.

Instead of using a static method you can have an EmailSender object attach to current HttpContext.This way each user will have its own EmailSender instance.
Here's the code in C# :
private static EmailSender _instance;
public static EmailSender GetEmailSender()
{
if(System.Web.HttpContext.Current != null)
{
if(! System.Web.HttpContext.Current.Items.ContainsKey("EmailSender"))
System.Web.HttpContext.Items["EmailSender"]=new EmailSender();\
return (EmailSender)System.Web.HttpContext.Current.Items["EmailSender"];
}
if(_instance==null)
_instance=new EmailSender();
return _instance;
}
It will work in web and windows application.
now every time you want to send an email you can do as follows:
GetEmailSender().SendMail(MailInfo mailInfo);

Also, if you're using VB.NET on Framework 3.5, you may want to look into using XML literals to build your HTML instead of StringBuilder. XML literals will make your code SUPREMELY more readable, and allow for very easy insertion of data into your message.
As a SIMPLE example...
Dim msg = <html><body>
Message sent at <%= Now.ToString() %>
</body></html>
myMailMessage.IsBodyHtml = True
myMailMessage.Body = msg.ToString()

Related

Is it bad to instantiate request and response objects in other functions?

I could not find a similar question, and this could be a dumb question, not sure, I couldn't figure out what keywords to search for.
For example, we have some sort of request/response pair for accessing information from the database (forgive me, using VB .NET at work, not my choice, so I'm just staying consistent)
Public Class ItemAddRequest
Public param1 As String = ""
Public param2 As String = ""
End Class
Public Class ItemAddResponse
Public returnParameter As MyItemObject = ""
Public Function Invoke(req As ItemAddRequst)
' SQL Queries go here
' Build my returnParameter
End Function
End Class
So these are used for the front end to get information to display on the front end, but is it bad to use these somewhere else in your code for the sole purpose of getting that info or adding that info? Generally you would want to modularize (invented word) that and use methods of my MyItemObject to do this, but we already have a large collection of things that would need to be changed so we are not doing that, at least for now. So for example we are doing something like this
Public Class ParentItemAddRequest
Public param1 As String = ""
Public param2 As String = ""
End Class
Public Class ParentItemAddResponse
Public returnParameter As MyParentItemObject = ""
Public Function Invoke(req As ParentItemAddRequest)
' SQL Query goes here to add parent
' Now also need to add a regular MyItemObject
Dim itemReq as new ItemAddRequest()
Dim itemResp as new ItemAddResponse()
itemReq.param1 = 'whatever
itemReq.param2 = 'whatever
itemResp.Invoke(itemReq)
me.returnParameter = itemResp.returnParameter
End Function
End Class
Doing this seems to work fine, but what kind of problems could we anticpate to cause? Or is this a completely normal thing? Seems odd to us. Thanks for the help.
If this code works than not much is wrong. If it aint broke then dont fix it. That being said, the only thing wrong with this code, i think, is that it uses wrong patterns. It just looks wrong. The only problem it would create is that it would confuse the hell out of new hires. Another serious implication of working this way is that the Class is now responsible for two things (1) declaring the data contract (2) defining the algo to fill it. This mixup is frowned upon according to SOLID principles. The mixup of responsibilities make it difficult to do unit testing and impact analysis.
When I find a Request class and Response class, the immediate assumption is that you guys are using the DTO pattern. The classes are assumed to be data contracts because of their naming convention. Now, the dtos are supposed to be simple POCOs devoid of any business logic. This is so that you can put all such classes in a seperate dll and different clients can use the shared data structures. So I wont be expecting the Invoke method there. I would expect that the dto is filled at the DAL layer either by handcrafted sqls in a DAO class or via some orm like entity framework.
With handcrafted sqls, I would expect a set of classes like Class ParentItemDAO with methods like Function Add(req As AddParentItemRequest) As AddParentItemResponse. Similarly I would expect a method Function GetParentItemById returning either a business object or a dto.

How to get a public variable (in a Module) to NOT share value between users

I'm working in an ASP.NET (VB) Web Application with Windows/Active Directory Authentication
I am using a module so that I can call public subroutines and functions, and reference variables, without having to instantiate a new object to access them on each page.
Within that module, I have some Public variables that I am using in multiple pages throughout the web application. I've recently realized that the values for these public variables in the module get shared between all users.
THE GOAL:
I want the value for these global variables to be specific to a single user and not shared between all sessions, and I do not want to have to instantiate a new object/class on every page that uses the variable.
THE CATCH:
I don't want to store the value in a client-side variable such as a cookie or session. I want the value to be stored on the SERVER but specific to each client/user.
The only thing I can think to do is setup a global collection/dictionary and store the variables with the authenticated user names, but then I need to have specific functions to get and set the values. While this will work, it requires all the references to these variables on all pages in the application to be updated.
EXAMPLE OF THE PROBLEM:
The below code shows how I am creating the public variable within the module and how the value is being set from one page and used on another. I'd like to continue to use this variable in the same way and share it's value between pages, but the value of the variable needs to NOT be shared between users.
-- MODULE.VB --
Public Module MyMod
Public myVariable as String = ""
End Module
-- MAINPAGE.VB --
Partial Class _Default
Sub Page_Load() Handles MyBase.Load()
myVariable = "HELLO WORLD"
End Sub
End Class
-- NEXTPAGE.VB --
Partial Class _Default
Sub Page_Load() Handles MyBase.Load()
Response.Write(myVariable)
End Sub
End Class
There are a LOT of pages in this application that will need to be manually updated if I have to use my userID-indexed collection solution, so I'm hoping there is a way to simply scope these variables differently or a way to disable the sharing between sessions.
Thanks in advance!
You didn't indicate whether or not the variables need to be persisted across page round trips or whether they are just used within each page's lifecycle.
If they are not persisted across pages, then perhaps the easiest solution is to have all of your pages inherit from a based page class and then move the values from the module into the base page. This way you won't have to change any variable references, only page inheritance.
If you do want to persist the values, completing the above changes makes it much easier to implement. You can then turn the member variables on the base page into properties and embed your user specific caching and fetching in the getter and setter.
For example, instead of:
Public MyVariable As String = ""
You would have something like:
Public Property MyVariable As String
Get
Return GlobalMyVariableCache(UserNameKey)
End Get
Set (Value As String)
GlobalMyVariableCache(UserNameKey) = Value
End Set
End Property
The problem you are coming across is a very common one in web programming. A Module's members are static - meaning there is one instance of them across the entire AppDomain of your application. Every user that accesses these will get the same object - you have already learned this.
Your options are exactly what you described. You could possibly replace the public variable in your module with a property whose getter you write to access a user-specific field in a dictionary (please remember thread safety when writing this getter code).
The much easier solution would be to use the Session. Session values are stored server-side and are user specific. The only thing that get's sent client side is the session key, and if you are using .Net authentication, this is likely already getting sent.
Good luck,

Shared methods in ASP.NET sessions

As a followup to the previous question I have asked "ASP.Net Architecture Specific to Shared/Static functions"
I am still struggling to understand the implications of using shared methods in ASP.NET.
So for example let us take the following code.
Public Shared Function GetCategoryByID(ByVal CategoryID As Guid) As Category
If Not CategoryID.Equals(Guid.Empty) Then
Dim res As New Category
Using sqlConn As New SqlConnection(My.Settings.ConnectionString)
sqlConn.Open()
Using dr As IDataReader = CategoryDataLayer.GetCategoryByIDQuery(sqlConn, CategoryID)
Return CType(BaseDataLayer.FillObject(res, dr), Category)
End Using
End Using
Else
Return Nothing
End If
End Function
Now I imagine client 1 connecting and running this method GetCategoryByID() from their session with the guid {A20E625F-2333-4742-BFD9-05BE7649222D}.
Let us now say that for example the process is about to execute the following line.
Using dr As IDataReader = CategoryDataLayer.GetCategoryByIDQuery(sqlConn, CategoryID)
At this point client 2 runs the same shared method but with the guid {6D806B82-FC7F-4124-AFB9-45E2689BC9F5}.
Does CategoryID not at this point become {6D806B82-FC7F-4124-AFB9-45E2689BC9F5} and therefor interfere with client 1 because now CategoryID has changed given that this is a shared method?
Could someone please clarify?
PS: I do apologize for what is essentially a duplicate post but in retrospect I don't feel the answer in the original post was clear enough (at least for me). Perhaps I wasn't specific enough either...
In your code sample, the variable res is a local variable of the shared method. No one, not even another shared method can touch that variable. It will exist for the lifetime of the method and then its gone. CategoryId is the exact same, its a local variable that cannot be touched from outside.
VB has another concept called Static which is very different than the C# version of static which can cause some confusion.
The only issue with Shared methods is shared state.
If you use a Shared field or Static variable, it will be shared across requests, and cause trouble.
However, a Shared method that doesn't use any external state or shared objects will work fine.
Even though the same method is being run, it is being run in two different contexts. Any variables local to that method (including the CategoryId parameter) are not shared.

How to use SQL from asp.net?

Building a relatively simple website, and need to store some data in the database (mainly authentication, but there's some per-user stuff). I've worked on a couple of websites previously, and used database there too, but never liked the way I accessed the database.
The way I usually did this was by having a SqlMethods.cs, which basically was a static class with a whole lot of static methods such as bool CheckUserExistence(string username, string password) and SqlDataReader GetJobListings(int advertiserId), each of which was essentially "open connection, call a sproc, return what it returns". This approach seems un-natural to me, however. I cant quite put my mind to what I want it to look like, but this seems...weird.
So, my question is this: how do you access the database from your asp.net projects?
I am using SQL2005. I also dont think I'll need an ORM of any kind, since there really isnt that much to get from the DB, but maybe its easier with one? Suggest something.
Thanks!
Edit:I currently decided to just create a static class Sql that will have a number of sql-related methods (such as ExecuteReader(sprocName, params[]), etc) that will call the sproc with the given parameters and just return the DataReader.
Then, have classes for specific functionality, such as Authentication with methods like CheckUserExistence(username, password) and LogoffUser(session). These methods would just call Sql.ExecuteReader("sp_Auth_CheckUserExistence", _some_params_here_) and process the result as needed.
I don't know if thats good or bad, but it seems to work for me at the moment. Plus, I like the way it feels - its all nicely separated functionality-wise.
So, any more suggestions?
Check out Linq to SQL or Linq to Entities:
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
http://msdn.microsoft.com/en-us/library/bb386964.aspx
The simplest way to do it is to create a data access class for each table in your database. It should have private variables and public properties for all of the columns in the table and the methods you describe should fill the internal variables (or use them to update the database).
Public Class MyTable
Private _id As Integer
Private _Name as String
Public ReadOnly Property ID As Integer
' Regular stuff here
End Property
Public Property Name As String
' Regular stuff here
End Property
Public Sub Load()
' Call SQL and get a data reader.
' Set _id and _Name from the data reader.
End Sub
End Class
Then, in your other code:
Dim mt As New MyTable
mt.Load()
' Now use mt.ID and mt.Name to access the data

Need to store a static value for the duration of a request. How?

I have an ASP.NET MVC application. I have come to an idea of generating autoincremented values to be used as unique element ids. The question is, how can I have and work with a global variable which should be there for the duration of a request (page generation) but no longer?
I thought of using TempData for this shared variable and then just delete this key when the page is done. But then, where in code to purge this TempData key? Obviously it has to be some very last piece of code where the page has been rendered already.
Any input is highly appreciated.
EDIT: I have a number of HTML helpers that can be called from various views and partial views, so declaring a variable on a page and passing it to each helper is obviously not a good solution. I wish to just use the helpers and know they all are getting unique ids behind the scenes.
Okay, I have googled a little bit and found a solution on ASP.NET forums.
http://forums.asp.net/t/1401685.aspx
Obviously, I can use the HttpContext.Current.Items collection to have my little static variable for the duration of a request.
If all you need is to store a number, the resources that would take to manage its lifestyle would take a lot more than just having a one static integer and always reusing it.
Do not bother deleting the key after each request. Just use a static (I think this is shared in visual basic) integer, use and increment it every time you need a unique value. Also take its mod with a ridiculously high number each time to make sure it will not be reused in a single request and it will never overflow.
Why don't you define your integer variable at the top of the page view file?
Use it throughout the view rendering execution and at the end of it you can easily leave it as is. You don't have to explicitly destroy anything. Your variables live for the duration of request only. IIS is stateless service (if you subtract Session, Cache and Application variables) so it doesn't really remember anything explicitly.
I would imagine you could use the Application_BeginRequest and Application_EndRequest methods in global.asax.cs; Note I can't double check the method names currently, but I think they are close.
You could create a member variable in your controller which would be regenerated for each request:
public class ItemController : Controller
{
private int _UniqueID = 0;
public ActionResult Index()
{
foreach (var item in items)
{
item.UniqueID = _UniqueID++;
}
// etc...
}

Resources