I have a static webmethod i.e (http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri) I want to call this method from Windows Task Scheduler. How should I do this?
You could use a PowerShell script. This has a check for the time, a commented-out Try..Catch in case you want to do something if an error is raised from the query, and records when it has run in the Application event log:
# Download the HTML of a web page.
# Make sure an event log source is created with New-EventLog -LogName Application -Source MyPSscript
# Only do this if the time is 5a.m. or later, to give the server a rest from midnight.
$currHour = (Get-Date).Hour
if ($currHour -ge 5) {
$web = New-Object Net.WebClient
#try {
$temp = $web.DownloadString("http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri")
#}
#catch {
# do nothing.
#}
write-eventlog -logname Application -source MyPSscript -eventID 1001 -entrytype Information -message "Fetched web page." -category 0
}
Have considered a different alternative to scheduling the call of a web method from Windows Task Scheduler?
For example, scheduling tasks from within an ASP.NET project is possible using the Revalee open source project.
Revalee is a service that allows you to schedule web callbacks to your web application. In your case, you would schedule a callback that would call your web method at a specific time. Revalee works very well with tasks that are discrete transactional actions, like updating some database values or sending an automated email message (read: not long running). The upside is that the code that schedules the callback, as well as the code that performs your action (i.e., your web method), would all reside within your app.
To use Revalee, you would:
Install the Revalee Service, a Windows Service, on your server. The Windows Service is available in the source code (which you would compile yourself) or in a precompiled version available at the Revalee website.
Use the Revalee client library in your Visual Studio project. (There is an MVC-specific version too.) The client library is available in the source code (which, again, you would compile yourself) or in a precompiled version available via NuGet.
You would register a future callback when your code calls the ScheduleWebMethodCallback() method (this example is assuming that you need your action to run 12 hours from now).
private void ScheduleWebMethodCallback()
{
DateTimeOffset callbackTime = DateTimeOffset.Now.AddHours(12.0);
// The callback should be in 12 hours from now
Uri callbackUrl = new Uri(string.Format("http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri"));
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
When Revalee calls your application back, your app would perform whatever action you have coded it to do in the web method you have listed above.
In case it was not clear above, the Revalee Service is not an external 3rd party online scheduler service, but instead a Windows Service that you install and fully control on your own network. It resides and runs on a server of your own choosing, most likely your web server (but this is not a requirement), where it can receive callback registration requests from your ASP.NET application.
I hope this helps.
Note: The code example above uses a synchronous version of ScheduleCallback(), the Revalee client library also supports asynchronous calls à la:
RevaleeRegistrar.ScheduleCallbackAsync(callbackTime, callbackUrl);
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.
Related
I'm trying to port a working Hangfire setup embedded in a Kestrel webserver to a console app. I've modified the web app so it still provides the Hangfire dashboard but doesn't start its own Hangfire server.
The code I must port uses Autofac. I've added the Hangfire.Autofac package to the console app and have already performed all the steps detailed in the answer to Hangfire Autofac .net core 3.1
When I create a job (using the web app) the console app Hangfire server tries to execute the job but I get this failure message:
The requested service 'AED.ServicesLayer.JobProcessing.ProcessManager' has not been registered.
Investigating this we examine the setup of Autofac in the console app. This is how I set up my container.
IConfiguration config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
var containerBuilder = new Autofac.ContainerBuilder();
containerBuilder.RegisterInstance(Log.Logger).AsImplementedInterfaces();
containerBuilder.RegisterModule(new RepositoryModule(config));
containerBuilder.RegisterType<UserService>().As<IUserService>();
containerBuilder.RegisterInstance(config).As<IConfiguration>();
containerBuilder.RegisterModule(new JobProcessingModule(config));
var container = containerBuilder.Build();
When the app is executed, hitting a breakpoint in JobProcessingModule proves the following line of code is executed.
builder.RegisterType<ProcessManager>().As<IProcessManager>();
It is very curious that the containerBuilder instance passed to JobProcessingModule.Load(containerBuilder) is not the same containerBuilder object on which RegisterModule is invoked.
However, experiments with simplified injectables suggest that this is normal, and the injected items are nevertheless visible in the registrations for the container that is returned.
Re-examining the logged failure we note that the class is mentioned by class name and not by interface. Changing the registration by removing the interface registration, like so
builder.RegisterType<ProcessManager>();//.As<IProcessManager>();
caused the ProcessManager to be found in the Hangfire console host but caused run-time errors in the web application when creating the job.
Registering it both ways caused ProcessManager to be found by both, with a new problem surfacing: cannot resolve dependencies. This, however, is merely a new case of the same problem.
While this allows me to move forward with getting a console host working, I do not like code I do not understand. Why should the console host require registration by class name when the web app does not?
Whatever is causing this has also caused Hangfire.IBackgroundJobClient to fail to resolve to the background job client. This is a hangfire class so it really does seem like there is a fundamental problem.
A lengthy investigation eventually revealed, confirmed by experiments, that this code
_recurringJobManager.AddOrUpdate(
insertResult.ToString(),
pm => pm.RunScheduledJobs(insertResult), interval.CrontabExpression
);
is responsible for the behaviour described in the question. AddOrUpdate is a generic method. When it is not explicitly typed it acquires its type from the class of the object passed to it. When the method is explicitly typed as the interface, like so
_recurringJobManager.AddOrUpdate<IProcessManager>(
insertResult.ToString(),
pm => pm.RunScheduledJobs(insertResult), interval.CrontabExpression
);
it remains compatible with the object, but the type acquired by Hangfire is the interface, and the console application can resolve ProcessManager from its interface.
Why the problem was not manifest in the web hosted Hangfire server remains a puzzle, but at least now I'm puzzled by the absence of a problem in a situation I don't have.
I have an app service in Azure running the front end from my MVC5 app, and another app service for web jobs. The app has several endpoints (GET Actions) which do some processing, send some emails or other simple task. Previously when we were hosted on a VPS, we used the Windows Task Scheduler to call each URL on a custom schedule. In Azure, the way we're currently doing this is with a Powershell script which uses CURL to fetch the URL and trigger the processing.
It seems messy though - as each powershell script has to be uploaded individually, and can't be viewed or changed after uploading. I've found various guides on deploying a .NET Core console app, but from what I can tell each job would need it's own project, deployed with it's own pipeline.
Is there a nicer way of doing this, are Webjobs even the right tool for this job, given the seemingly simple task we're performing.
As far as I understand your use case, you can use Azure Function App Timer Trigger to accomplish it.
A timer trigger lets you run a function on a schedule.
The following example shows a C# function that is executed each time the minutes have a value divisible by five (eg if the function starts at 18:57:00, the next performance will be at 19:00:00). The TimerInfo object is passed into the function.
[FunctionName("TimerTriggerCSharp")]
public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
{
if (myTimer.IsPastDue)
{
log.LogInformation("Timer is running late!");
}
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
The attribute's constructor takes a CRON expression or a TimeSpan. You can use TimeSpan only if the function app is running on an App Service plan. TimeSpan is not supported for Consumption or Elastic Premium Functions.
CRON (NCRONTAB expressions)
I am creating an ASP.NET Web API using .NET 4.5.2. The API needs to connect to a runspace on startup. I have questions about when this Startup.Configuration method actually runs though. It does not seem to run when I start the website or app pool. It seems to wait until the first time somebody tries to access the website. Is this correct? Also, it seems to run again at random times. I have seen it run after 2 hours, 4 hours, and 16 hours. It doesn't really make any sense. Can somebody clear up for me when these methods should run? Also, if you have a suggestion for a better place to put them given that I want it to be a shared runspace for all connections and that I want it to run before anybody tries to connect to the API. Perhaps a separate service?
Also, would it be worth looking into ASP.NET CORE? I don't need it to run on anything other than IIS, however if there is a benefit to using CORE I am at a point where it will be easy to switch.
public partial class Startup
{
public Cache GlobalCache;
public static PowershellRunspace PSRunspace;
public static ActiveDirectory ADObjects = new ActiveDirectory();
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
GlobalCache = new Cache();
AppLog log = new AppLog();
log.InfoLog("Starting PowerShell Runspace in Hangfire...", true);
GlobalConfiguration.Configuration.UseSqlServerStorage("Hangfire");
BackgroundJob.Enqueue(() => log.InfoLog("Hangfire started!", true));
BackgroundJob.Enqueue(() => ADObjects.Startup(true));
BackgroundJob.Enqueue(() => StaticRunspace.Start());
app.UseHangfireDashboard();
app.UseHangfireServer();
}
}
Assuming you're running this application in IIS (and not self-hosting), the following rules apply:
The Configuration method runs once per application start.
The application is started lazily (on the first request to it via HTTP/S).
IIS has a few settings that affect the application:
An idle timeout. If the app isn't accessed via a request in 20 minutes then the application is unloaded / put offline. The next request starts it again.
A regular app pool recycle. It just straight up restarts the application by recycling the app pool every 1740 minutes.
So the behavior you're seeing is likely due to the infrequent access of the application, combined with the IIS defaults. If you'd like to see or configure the settings, you can do so by going into IIS, right clicking on your app pool, and selecting Advanced Settings.
I was trying out one functionality of BizTalk from the below link
https://masteringbiztalkserver.wordpress.com/category/pipelines/
Till now I never had to go to event log to check for any entries.
Now when I am trying to get a custom message logged in event Log, from BizTalk application, I dont see any relevent entry from BizTalk other than 2 entries when I restart the BizTalk Host instance.
From my research I had written down the below code in Expression shape in the application Orchestration:
xmlMessage = InputMessage;
stringMessage = xmlMessage.OuterXml;
System.Diagnostics.EventLog.WriteEntry("BizTalk Server", stringMessage);
Here the InputMessage is a message defined in orchestration for sample Schema that I have created.
My application got build and deployed properly and it is also processing the messages properly. Its just that I don't see any log in event viewer for my code or for the suspended messages when I intentionally stop the send port.
The discussionfrom below link also didnt help
No eventlogs from BizTalk
I have BizTalk Server configured on my Windows 7 Ultimate machine. I am the administrator of the machine.
A few points on this:
BizTalk sever will not log an event for a suspended message, that's why you dont' see one.
You should never use the BizTalk Server Event Source since the BizTalk product owns that
You can very easily create you own custom Event Source using PowerShell.
To create a custom Event Source, use something like:
new-eventlog -logname "Application" -Source "MyApplicationThatLogs"
To write with this Event Source, use something like:
System.Diagnostics.EventLog.WriteEntry("MyApplicationThatLogs", "Some Error Occured!", System.Diagnostics.EventLogEntryType.Error, 100, 0);
Rather than using System.Diagnostics.EventLog for debugging purposes I would recommend that you use the BizTalk CAT Instrumentation Framework.
For a pipeline
TraceManager.PipelineComponent.TraceInfo(stringMessage);
For a Orchestration
Microsoft.BizTalk.CAT.BestPractices.Framework.Instrumentation.TraceManager.WorkflowComponent.TraceInfo(stringMessage);
It allows for real-time tracing when needed, "you can enable tracing on a production server with only a negligible impact on performance (when tracing to a file)."
I have to solve the following problem. We got an ASMX web service which is requested every two minutes. If this service is not requested for ten minutes an email should be sent. We want to realize this by using the scheduled tasks. We imagined it like this
1. Creating a scheduled task which will send an email every ten minutes
2. If the service is requested the execution time for the task will be set to ten minutes from now and so the execution time cannot be reached
- If the service is not requested the execution time will be reached and the email is sent
Is there a way to solve this in ASP.NET or are there maybe better solutions?
Thanks for any response.
You may want to take a look at the Revalee open source project.
You can use it to schedule web callbacks at specific times. In your case, you could schedule a web callback (10 minutes in the future) every time your web service is used. When your web service receives the callback, it can determine whether or not the service has been used recently. If the web service has been active, then the callback is ignored; if the web service has been inactive, then it can send out an email message.
For example using Revalee, you might:
Register a future (10 minutes from now) callback when your application launches.
private DateTimeOffet? lastActive = null;
private void ScheduleTenMinuteCallback()
{
// Schedule your callback 10 minutes from now
DateTimeOffset callbackTime = DateTimeOffset.Now.AddMinutes(10.0);
// Your web service's Uri
Uri callbackUrl = new Uri("http://yourwebservice.com/ScheduledCallback/YourActivityMonitor");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
Anytime your web service is used, you register another callback and store the date & time that your service was active as a global value.
lastActive = DateTimeOffset.Now;
ScheduleTenMinuteCallback();
Finally, when the web schedule task activates and calls your application back, then you test the value of the global
private void YourActivityMonitor()
{
if (!lastActive.HasValue || lastActive.Value <= DateTimeOffset.Now.AddMinutes(-10.0))
{
// Send your "10 minutes has elapsed" email message
}
}
I hope this helps.
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.