I have a requirement that a certain email distribution list should be notified every so often (still to be determined) about user accounts that are nearing expiration.
I'm wondering the best way to achieve this, I know its generally a bad idea to spawn another thread within asp.net to handle this type of thing, so I'm thinking maybe a simple service is the way to go but for something so small this seems like it might be slightly overkill.
Ideally I'd like something that doesnt require much babysitting (eg. checking service is running).
I have also suggested having a page in the site with this type of information but it is likely that it could be a few days before this is checked. We also cannot let users extend their own expiration date.
Are there any other viable options.
The best suitable method to work on it according to is
create a application which will select list of all users whose account expiry date is nearby (eg. 10 days from today) as per your requirement.
This application will be scheduled as an daily execution (you will create an exe with log file to display errors raised and total number of emails sent in one execution.)
This application will fetch all the records based on criteria and send the emails to all yours using the basic HTML template. and once the email is sent, you will update a column (notificationFlag) in your database as 1 if you have sent is once in last 10 days. else by default it will be 0
you can schedule the exe by the end of the day at 12:10 am (just incase your database server and webserver is not matching in time) every day. .
This is something I've done which is similar to Prescott's comment on your answer.
I have a website with an administrative page that reports on a bunch of expiration dates.
This page also accepts a QueryString parameter SEND_EMAILS, so anytime an administrative user of the site passes the QueryString parameter SEND_EMAILS=true a bunch of emails go out to all the users that are expiring.
Then I just added a windows scheduled task to run daily and load the page with the SEND_EMAILS=true parameter.
This was the simple code I used to issue the webrequest from the console in the scheduled task:
namespace CmdLoadWebsite
{
class Program
{
static void Main(string[] args)
{
string url = "http://default/site/";
if (args.Length > 0)
{
url = args[0];
}
Console.WriteLine(GetWebResult(url));
}
public static string GetWebResult(string url)
{
byte[] buff = new byte[8192];
StringBuilder sb = new StringBuilder();
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
Stream webStream = response.GetResponseStream();
int count = 0;
string webString;
do
{
count = webStream.Read(buff, 0, buff.Length);
if (count != 0)
{
webString = Encoding.ASCII.GetString(buff, 0, count);
sb.Append(webString);
}
}
while (count > 0);
return(sb.ToString());
}
}
}
Related
I try to use my application (with TLSharp) but suddenly by using TelegramClient .SendCodeRequestAsync function, I get This Exception :
"Flood prevention. Telegram now requires your program to do requests
again only after 84894 seconds have passed (TimeToWait property). If
you think the culprit of this problem may lie in TLSharp's
implementation, open a Github issue "
after waiting for 84894 sec, It show this message again.
(I wait and try several times but messages doesn't differ:( )
Someone told me that its Telegram limits. Is it right?
Do you Have better idea to Send message/file to a telegram account?
It might be a late answer but can be used as a reference. the first problem is that Telegram APIs don't let each phone number to send code request more than 5 times a day. the second problem is shared session file that you use for TelegramClient by default. so you should create a custom session manager to separate each phone number session in a separate dat file.
public class CustomSessionStore : ISessionStore
{
public void Save(Session session)
{
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sessions");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var file = Path.Combine(dir, "{0}.dat");
using (FileStream fileStream = new FileStream(string.Format(file, (object)session.SessionUserId), FileMode.OpenOrCreate))
{
byte[] bytes = session.ToBytes();
fileStream.Write(bytes, 0, bytes.Length);
}
}
public Session Load(string sessionUserId)
{
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sessions");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var file = Path.Combine(dir, "{0}.dat");
string path = string.Format(file, (object)sessionUserId);
if (!File.Exists(path))
return (Session)null;
var buffer = File.ReadAllBytes(path);
return Session.FromBytes(buffer, this, sessionUserId);
}
}
then create your TelegramClient like this:
var client = new TelegramClient(apiId, apiHash, new CustomSessionStore(), phoneNumber);
I guess you are closing and starting your application many times or repeating this method. After 10 times the telegram API makes you wait for about 24 hours to prevent flood.
It's a Telegram limit, my advice: Wait 2-3 minutes between calling SendCodeRequestAsync()
I am working on a project that is a .NET WebForms solution that contains many PageMethod's to act like an MVC hybrid.
We have a registration service in our product that upon typing your username, will call a service to immediately check if the username has already been chosen (without calling a post-back).
What would be the most appropriate way of preventing someone from mapping out the entire username database by brute-forcing requests for true/false answers on if a string exists as a username.
The best method I can currently think of is throttling requests based on session, which would not completely stop the problem, but like encryption, make the time-cost to effectively succeed not worth it for the intruders.
In my head I was thinking along the lines of:
Public Function SomeFunction() as String
Dim throttle As Throttle = New Throttle()
If Not HttpContext.Current.Session("IsUsernameExistsThrottle") Is Nothing Then
throttle = DirectCast(HttpContext.Current.Session("IsUsernameExistsThrottle"), Throttle)
If Not throttle.SetExpiry Is Nothing Then
If throttle.SetExpiry > DateTime.Now Then
Throw New Exception("Please wait 1 minute before accessing this functionality again.")
Else
throttle.SetExpiry = Nothing
End If
Else
throttle.RequestCount += 1
If throttle.RequestCount >= 10 Then
throttle.SetExpiry = DateTime.Now.AddMinutes(1)
End If
End If
Else
throttle.SetExpiry = Nothing
throttle.RequestCount = 1
End If
HttpContext.Current.Session("IsUsernameExistsThrottle") = throttle
Return SomeValue
End Function
Public Class Throttle
Public RequestCount As Integer
Public SetExpiry As DateTime?
End Class
What this function would do is allow the first 10 requests for free, and then throttle every request afterwards to 1 per minute.
Any thoughts or suggestions, or recommendations for best practice?
Thanks,
I just started using Microsoft Exchange Web Services for the first time. Want I want to be able to do is the following:
Create Meeting
Update Meeting
Cancel/Delete Meeting
These meetings are created in an ASP.NET MVC application and saved into a SQL Server database. I simply wish to integrate this with the on site Exchange Server. So far, I'm able to created my meeting with the following code:
public static Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
{
var tcs = new TaskCompletionSource<string>();
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = CredentialCache.DefaultNetworkCredentials;
//service.UseDefaultCredentials = true;
// I suspect the Service URL needs to be set from the user email address because this is then used to set the organiser
// of the appointment constructed below. The Organizer is a read-only field that cannot be manually set. (security measure)
service.AutodiscoverUrl(from);
//service.Url = new Uri(WebConfigurationManager.AppSettings["ExchangeServer"]);
Appointment meeting = new Appointment(service);
meeting.Subject = subject;
meeting.Body = "<span style=\"font-family:'Century Gothic'\" >" + body + "</span><br/><br/><br/>";
meeting.Body.BodyType = BodyType.HTML;
meeting.Start = begin;
meeting.End = end;
meeting.Location = location;
meeting.ReminderMinutesBeforeStart = 60;
foreach (string attendee in to)
{
meeting.RequiredAttendees.Add(attendee);
}
meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
tcs.TrySetResult(meeting.Id.UniqueId);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
This successfully creates my meeting, places it into the user's calendar in outlook and sends a meeting request to all attendees. I noticed the following exception when attempting to call meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy); twice:
This operation can't be performed because this service object already has an ID. To update this service object, use the Update() method instead.
I thought: Great, it saves the item in exchange with a unique id. I'll save this ID in my application's database and use it later to edit/cancel the meeting. That is why I return the id: tcs.TrySetResult(meeting.Id.UniqueId);
This is saved nicely into my application's database:
Now, I am attempting to do the next part where I update the meeting, but I cannot find a way to search for the item based on the unique identifier that I'm saving. An example I found on code.msdn uses the service.FindItems() method with a query that searches the subject:
string querystring = "Subject:Lunch";
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, querystring, view);
I don't like this. There could be a chance that the user created a meeting outside of my application that coincidentally has the same subject, and here come's my application and cancel's it. I tried to determine wether it's possible to use the unique id in the query string, but this does not seem possible.
I did notice on the above query string page that the last property you can search on is (property is not specified) that searches in "all word phase properties.". I tried thus simply putting the id into the query, but this returns no results:
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, "AAMkADJhZDQzZWFmLWYxYTktNGI1Yi1iZTA5LWVmOTE3MmJiMGIxZgBGAAAAAAAqhOzrXRdvRoA6yPu9S/XnBwDXvBDBMebkTqUWix3HxZrnAAAA2LKLAAB5iS34oLxkSJIUht/+h9J1AAFlEVLAAAA=", view);
Use the Appointment.Bind static function, providing a service object and the ItemId saved in your database. Be aware with meeting workflow (invite, accept, reject) can re-create a meeting on the same calendar with a new ItemId. But if you are just looking at the meeting you make on your own calendar, you should be OK.
I have written the following inside my RegisterRoutes() in Global.asax in webforms application.
I have an xml file called CacheInfo.xml that stores the details of cached pages.The default page has an entry in the xml called EnDefaultPage, which contains two child nodes.
The child node LastUpdationTimeStamp stores, last updation timestamp (unix timestamp in seconds ) of the cache for Default page.
The child node ExpiryTimestamp stores the timestamp at which the cache will be expired.So if the expiry timestamp is greater than lastupdation timestamp, the file from Cache will be loaded (Default.html).Currently the script is working, but it is not routing to the Default.html although the conditional block that defines the route is being executed.I couldn't find the exact reason behind the issue.Can anybody suggest me a fix.All the other routes are working perfectly.
My code is attached below.
ublic void RegisterRoutes(RouteCollection routes)
{
string relPath = "~/CacheInfo.xml";
string absPath = Server.MapPath(relPath);
XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
xdoc.Load(
absPath
);//loading XML in xml doc
string nodeName="", nodeVal="",upStamp="0",expiry="0";
int iUpStamp,iExpiry;
upStamp = xdoc.GetElementsByTagName("EnDefaultPage")[0].SelectSingleNode("LastUpdationTimeStamp").InnerText;
expiry = xdoc.GetElementsByTagName("EnDefaultPage")[0].SelectSingleNode("ExpiryTimeStamp").InnerText;
iUpStamp = Convert.ToInt32(upStamp);
iExpiry = Convert.ToInt32(expiry);
if(!String.IsNullOrEmpty(upStamp)) {
if (iExpiry > iUpStamp)
{
System.Diagnostics.Debug.WriteLine("stamp is " + upStamp + " Expiry is " + expiry);
// routes.MapPageRoute("EnHome1", "", "~/en/DefaultCache.aspx");
routes.MapPageRoute("EHome", "en/", "~/en/Default.html");
//this routing is not working
}
else
{
}
}
routes.MapPageRoute("GArticle", "Gallery/{slug}", "~/Gallery/Article.aspx");
routes.MapPageRoute("GCategory", "Gallery/Categories/{slug}", "~/Gallery/Categories.aspx");
routes.MapPageRoute("GSlideShow", "Gallery/{slug}/{id}", "~/Gallery/SlideShow.aspx");
routes.MapPageRoute("Article", "en/{slug}", "~/english/Article.aspx");
routes.MapPageRoute("Category", "en/Categories/{slug}", "~/english/Categories.aspx");
routes.MapPageRoute("enFeed", "en/category/english/{slug}/feed", "~/en/feed.aspx");
routes.MapPageRoute("teFeed", "te/category/telugu/{slug}/feed", "~/te/feed.aspx");
routes.MapPageRoute("Tags", "en/Tags/{tag}", "~/english/Tags.aspx");
routes.MapPageRoute("tArticleHtml", "te/{slug}.html", "~/telugu/Article.aspx");
routes.MapPageRoute("tArticle", "te/{slug}", "~/telugu/Article.aspx");
routes.MapPageRoute("tCategoryHtml", "te/Categories/{slug}.html", "~/telugu/Categories.aspx");
routes.MapPageRoute("tCategory", "te/Categories/{slug}", "~/telugu/Categories.aspx");
routes.MapPageRoute("tTagsHtml", "te/Tags/{tag}.html", "~/telugu/Tags.aspx");
routes.MapPageRoute("tTags", "te/Tags/{tag}", "~/telugu/Tags.aspx");
}
}
If I read your intent correctly, you want the user to be directed to default any time their access is expired. If so, you can't get there from here.
RegisterRoutes is used to register routes as the application starts up.The last 3 words are the clue as to why certain logic will not work later in the application.
Now to your RegisterRoutes. Here is the logic.
Get expiration date
Get timestamp
If the expiration date is greater than last updated, when the application starts, route the user to default
If you truly mean "at startup determine whether to route every page that can be expired to default, every time" then you have the correct logic and it is working as expected. The fact you asked the question says that is not your intent. You want a decision made on a page access by page access basis. If I am correct, you can't do it in RegisterRoutes. You will have to implement the "caching logic" elsewhere.
My suggestion, rather than building this by hand, is look into software that handles caching.
I created an web application where a lot of words was needed in the application which take a lot of time and thinking when u need to write it.
Let's suppose the session timeout after 30 minutes,i started writing a lot of words and while thinking and writing the session timeout and redirect to the login page and all written data is lost.
Any idea for this problem except extending session timeout period ???
Currently your session is created and managed as In-Process mode and in this mode you cannot recover session state once it reaches timeout stage. You may set SQL Server Mode and configure your application for SQL Server Mode so your data will be persisted into Sql Server database.
Profile Properties is an alternate to save the state.
You can use some ajax function that regularly "calls home" (executes some dummy code on the server). This will keep the session alive as long as that user has this page open.
You might need to explicitly use the Session in that callback, such as
Session["LastAccess"] = DateTime.Now;
just to keep it alive.
If you execute this call every 15 minutes, the session will not time out and the load on the server is minimal.
Use asynchronous programming model which allowing some portion of code to be executed on a separate threads.
There are three style of Programming with APM
Wait Until Done Model
Polling Model
Callback Model
Based on your requirement and result you can choose the model which is more appropriate.
For instance, let us say you can to read the file and wait until done and sample code is
byte[] buffer = new byte[100];
string filename =
string.Concat(Environment.SystemDirectory, "\\mfc71.pdb");
FileStream strm = new FileStream(filename,
FileMode.Open, FileAccess.Read, FileShare.Read, 1024,
FileOptions.Asynchronous);
// Make the asynchronous call
strm.Read(buffer, 0, buffer.Length);
IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
// Do some work here while you wait
// Calling EndRead will block until the Async work is complete
int numBytes = strm.EndRead(result);
// Don't forget to close the stream
strm.Close();
Console.WriteLine("Read {0} Bytes", numBytes);
Console.WriteLine(BitConverter.ToString(buffer));
But creating your threads are not necessary or suggesting, .NET supports a built in thread pool that can be used in many situation where you thinking to create your own threads. Sample code
static void WorkWithParameter(object o)
{
string info = (string) o;
for (int x = 0; x < 10; ++x)
{
Console.WriteLine("{0}: {1}", info,
Thread.CurrentThread.ManagedThreadId);
// Slow down thread and let other threads work
Thread.Sleep(10);
}
}
Instead of creating a new thread and controlling it, we use the ThreadPool to this work by using its QueueWorkItem method
WaitCallback workItem = new WaitCallback(WorkWithParameter));
if (!ThreadPool.QueueUserWorkItem(workItem, "ThreadPooled"))
{
Console.WriteLine("Could not queue item");
}