I am using ASP.NET Web forms,
When a user submit a page, an email will be sent to many people which is slowing the post-back,
what is the best way to send the emails without slowing the reloading of the page?
thanks
You can use the System.Net.Mail.SmtpClient class to send the email using the SendAsync() method.
var smtpClient = new SmtpClient();
var message = new MailMessage(fromAddress, toAddress, subject, body);
smtpClient.SendCompleted += new SendCompletedEventHandler(OnSendCompletedCallback);
smtpClient.SendAsync(message, null); // Null Or pass a user token to be send when the send is complete
If you need to handle perform some additional stuff after the async send is complete you can subscribe to the SendCompleted event of the SmtpClient as well.
private void OnSendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Handle the callback if you need to do anything after the email is sent.
}
Here is a link to the documentation on MSDN.
I've found unless you're building a very small website, it's almost always best to send mail from a separate Windows Service.
Your Web front-end logs the mail to be sent in your database for example. This has a nice side-effect of allowing you do also develop an sent folder, outbox, etc. Your windows service polls the mail table and does the actual sending.
Sending mail can cause lots of exceptions, can be slow, can timeout, host processes reaped, etc. Handling it in the background makes a lot of sense in many situations.
Here's more information on Windows Services.
Related
I am still new to signalr. I want to make chat application with signalR and having a problem with the personal chat and groups because the connection id always changes every time the user and reconnect.
Question : How we know which id user is reference the specific user. if the connection id always change.
(because if the user open another tab in their browser the signalR will recognize them as another user. How do we know that the id is the same person)
Is there any unique property from signalR that we can save in database so when the user login when can recognize the user ?
You can use UserNames of the logged in users. Depending on the technology you use, you can utilize different methods. The way I do it in MVC is like the following:
Hub:
public class ChatHub :Hub
{
public void SendMessage(string sender,string receiver, string msg)
{
MessageService messageService = new MessageService();
long msgId = messageService.Add(sender, receiver, msg);
Clients.User(receiver).receiveMessage(sender, msg, msgId);
Clients.User(sender).receiveMessage(sender, msg, msgId);
}
}
View:
$('#send').click(function () {
hub.invoke("SendMessage", "#User.Identity.Name", "#ViewBag.Receiver", $('#message').val());
});
The sender UserName can be obtained by #User.Identity.Name (in MVC) and the receiver UserName can be read when the sender is opening the receiver chat.
Update:
Regarding Asp.Net Web Forms, check if the following helps:
SignalR-with-ASP-NET-One-to-one-and-Group-Chat
SignalR is doing what it should do with each connect/reconnect. Your user is establishing a new connection, so they get a new connection ID.
If they open in a new tab that will create a new connection. You have to work out users being currently connected and how you want to handle.
If you take a look at the docs you can see they have examples for mapping users to connections.
I have a database of email subscribers; approx. 1800 in the list. We have our own exchange server. I'm using the code below to grab each email address from the DB and send email, one at a time. I'm using an ASP.NET 4.0 Web Form to do this.
I notice the page hanging when the emails are being sent. What would be the best approach for implementing this - use a console app? How would I go about stress testing something like this?
I'm also getting an unhandled error message in the server log:
Event code: 3001
Event message: The request has been aborted.
// Call data access method via business class
TaxSalesBusiness bizClass = new TaxSalesBusiness();
DataSet ds = bizClass.GetSubscribers();
foreach (DataRow row in ds.Tables[0].Rows)
{
// Check well-formedness of each email adddress
if (!IsWellformedEmailAddr(row["Email"].ToString()))
{
// Ignore and log mal-formed email address
LogError(row["Email"].ToString()
+ " is a malformed email address. Message was not sent to this subscriber "
+ row["Name"].ToString() + ".", "");
continue;
}
else
{
string toAddress = row["Email"].ToString();
smtpClient.Send(fromAddress, toAddress, message.Subject, message.Body);
}
}
I notice the page hanging when the emails are being sent. What would
be the best approach for implementing this - use a console app?
Yes.
And you can SendAsync instead of waiting for one email to be sent before you send the next one. I don't know how much your Exchange server will like that, though.
The problem with your current approach is that sending 1800 emails one by one is going to take a lot of time and using a web page to perform such a long operation will probably timeout the request. You can perhaps do it on an async page and launch everything on its own thread, but that's just complicating things more than it needs to when you can perfectly do this in a Console App with far less lines of code and complications. Remember the KISS principle.
Another (more stable) solution could be to forward the mails to a (database?) queue, and have a Windows Service poll that queue once in a while. If there are new things on the queue the Windows Service is responsible for sending the e-mails.
This approach will help you steer clear from performance issues in your website, and it could make the delivery of the mails to be more reliable.
In LiveId Web Auth scenario, when client application receive "clearcookie" request, it is responsible for clearing the authorization cookies and should confirm success by returning any GIF image through http. Using reference implementation of liveid web auth in asp.net-mvc looks like:
if (Request["action"]=="clearcookie")
{
string contentType;
byte[] content;
wll.GetClearCookieResponse(out contentType, out content);
return this.File(content, contentType);
}
Where wll.GetClearCookieResponse is implemented as:
public void GetClearCookieResponse(out string type, out byte[] content)
{
const string gif =
"R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7";
type = "image/gif";
content = Convert.FromBase64String(gif);
}
So the GetClearCookieResponse method creates byte[] array containg tiny hardcoded GIF.
Is there any particular reason why responding with GIF is required? Why not just plain text ("OK") or JSON?
Are there any other (than LiveId) protocols using returning GIF as a response? I'm asking because I want to know if there is any reason to adopt this solution in projects requiring similar scenarios of communication.
When a user signs out of Windows Live or a Windows Live pplication, a best-effort attempt is made to sign the user out from all other Windows Live applications the user might be signed in to. This is done by calling the handler page for each application with 'action' parameter set to 'clearcookie' in the query tring. The application handler is then responsible for clearing any cookies or data associated with the login. After successfully signing the user out, the handler should return a GIF (any GIF) as response to the action=clearcookie query.
This function returns an appropriate content type and body response that the application handler can return to signify a successful sign-out from the application.
Your code should only return the image (.gif) as specified, and nothing else. An extra byte will trigger an error (malformed image).
I suppose it could be any type of expected response and suspect they chose a GIF because it would cause a browser to promptly hang up the connection when received.
So I know the best practice would be to run my Flex app over ssl along with implementing other forms of security however that isn't an option at this point (for monetary reasons and the app simply doesn't need that much security otherwise my sponsors would pay for it). However, I would like to implement some form of security and I'm wondering whether it's even worth it when I don't have ssl to protect the transactions.
So my setup is that I have a ASP.Net server side with a Flex UI. Right now the UI is the only thing that protects access to the sever: the server doesn't do any sort of verification during each request, it just assumes the person is allowed to do it. Obviously, anybody could write a program to generate posts (even if I could use SSL it would be like swiss cheese). Like I said before, security isn't a big deal, this is an internal app and it's nothing critical, however I do believe in doing things right. Would keeping the user info in session be a viable option and then verifying that the given user has permission, etc. Perhaps some sort of token system?
What would your preferred method of protecting this setup be?
...and no, I won't give you the url :)
ASP.NET Session itself is token based security and yes you can easily implement that by doing
[WebMethod(true)]
and yes, any web method requires login to be done first, it should call User.IsAuthenticated, that verifies the session token.
You can easily implement form authentication (let web.config empty, you can use FormsAuthentication in code).
for example,
[WebMethod(true)]
public string DoLogin(
string username,
string password)
{
//.. do your verification
FormsAuthentication.SetAuthCookie(username,false);
return "Login Sucessful";
}
[WebMethod(true)]
public string ChangePassword(
string oldPass,
string newPass)
{
// verify user is logged on or not..
if(!User.IsAuthenticated)
return "Please Login";
// The code below is secure, only
// authenticated user will go through below
// change pass...
return "Password Changed Successfully.";
}
We developed many Flex+ASP.NET sites, we did exactly same thing, but instead of return "string" we usually return a class like following...
public class WSResult<T>{
public bool Successful;
public string Message;
public T Result;
public T[] Results;
}
The convention is simple, if method was successful then you return Success = true, and depending upon whether you want to return an array of items or just single item, you can return either Results or Result. In case if there has been any error or unathorized access you can set Successful=false and set Message as detailed string. As per following example.
[WebMethod(true)]
public WSResult<BusinessUser> DoLogin(
string username,
string password)
{
try{
BusinessUser user = BusinessUser.GetByUsername(username);
if(user==null)
throw new Exception("User not found");
if(user.Password != password)
throw new Exception("Password did not match");
return new WSResult<BusinessUser>{ Result=user };
}catch(Exception ex)
{
// this will even catch any DAL exceptions or any system error as well
// Log Exception... somewhere for tracking...
return new WSResult<BusinessUser>{ Successful=false, Message = ex.Message };
}
}
Unfortunately, I know diddly squat about flex, but I think I can help anyway. I think you have two reasonably good options.
First though, we need to clarify something... Are you saying the server doesn't do any authorization? Does it at least have the ability to authenticate a user? Do you have any control over the server code? If not, I don't think the following suggestions will help. I'm not sure how you're supposed to secure a server with just client side code. Maybe there is a way, but I can't think of it.
1) Use HTTP digest authentication. This requires that the server is configured to understand it and that there is support in the flex api for adding the appropriate auth header to the HTTP request. The server authenticates the user by his password and can check what operations can be performed by said user against some authorization mechanism.
2) Follow the guidelines in this article to implement the authentication scheme that many atom publishing endpoints use. The flex api will have to provide some support for this, maybe there is an existing third party lib though. If you can get access to the HTTP headers you should be able to implement the rest.
Good luck.
How are you commuicating with the server SOAP. REST etc?
If it is SOAP have a look at the answer to this question
General Password Security && Implementation in Actionscript 3
and here's a link how to add the header to the SOAP message
How to add a "flat" message header to a flex web service call?
Hope this helps
Jon
I want my asp.net mvc framework system to send an e-mail everytime a certain action (inside a certain controller) is fired off. Are there any third party libraries or .net standard ways to accomplish this?
A more up to date method would be to use System.Net.Mail - this is the 2.0 replacement for System.Web.Mail.
Something like this, called from either a BaseController (if there are other controllers that need this) the actual controller in question.
I have the following code inside a static class to handle mailing simple plain text items from the server:
internal static void SendEmail(MailAddress fromAddress, MailAddress toAddress, string subject, string body)
{
var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
};
var client = new SmtpClient("smtpServerName");
client.Send(message);
}
Obviously, you'd probably want some error handling etc in there - Send can throw an exception for example if the server is refusing connections.
Create a BaseController from which all your other controllers inherits.
In the BaseController override the OnActionExecuted Method and insert your code for sending the email.
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Send mail here
base.OnActionExecuted(filterContext);
}
}
The SmtpClient Class with the other System.Net.Mail classes are easily utilized from any .NET program to send mail. You just need to point it to an available and willing SMTP server.
Well its not really hard to send a Email using .NET. You can just send the mail from inside your action.
But, I think we talk little about logging here, and for logging there is a range of 3th party libraries. I know there is one called Log4Net.
Most of these logging frameworks makes it possible to config how logs are stored, and porsibly also a setting to send a email, when it logs something.
But in your scenario, it would just write a plain simple mail function, that sends the mail, when the user enters the action. You can make look at: http://www.developer.com/net/asp/article.php/3096831 - its a demo of sending a mail using .NET - webforms though, but the basic things still apply to MVC.