How can I schedule a task with Umbraco Cms. I would like to create scheduled emails with Umbraco 9.
I have tried unsuccessfully to get a documentation that could help. Could you please help or refer me to a documentation
Just write an API-Controller, which does the work. Then use the windows task scheduler or a cron job on linux to call the url of the API.
public class EmailsController : UmbracoApiController
{
[HttpGet]
public string Create()
{
// Do whatever you need
return "OK";
}
}
Then call the url https://yoursite.com/umbraco/api/emails/create
Firstly, have a read about hosted services, which are a feature provided by the .NET 5 framework, and which Umbraco are using themselves.
In Umbraco v9, you can implement your own version by inheriting from RecurringHostedServiceBase
The documentation is lacking on this, but have a look at the Umbraco implementation to see some examples - https://github.com/umbraco/Umbraco-CMS/tree/v9/dev/src/Umbraco.Infrastructure/HostedServices
This is also a useful post that provides some further details - https://our.umbraco.com/forum/umbraco-9/106304-creating-scheduled-tasks-in-umbraco-9
An example:
public class YourScheduledTask : RecurringHostedServiceBase
{
private readonly ILogger<YourScheduledTask> _logger;
public YourScheduledTask(ILogger<YourScheduledTask> logger)
: base(TimeSpan.FromMinutes(2),
TimeSpan.FromMinutes(2))
{
_logger = logger;
}
public override async Task PerformExecuteAsync(object state)
{
try
{
// your logic here
}
catch (Exception e)
{
_logger.LogError("exception when persisting collections: {exception}", e.ToString());
}
}
}
Don't forgot to resgister this in the IOC:
public class IoCComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddHostedService<YourScheduledTask>();
}
}
Related
I have an older .NET 4.8 project that needs to use Airbrake. The project is using Unity for its IoC container, implementing the standard Repository Service pattern.
There's very little in the way of ASP.NET examples.
I am looking to do something like this:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType(typeof(ILogger<>), typeof(ILogger<>));
container.RegisterType<IMyService, MyService();
}
public class MyController
{
private readonly ILogger<MyController> _logger;
private readonly IMyService _myService;
public MyController(ILogger<MyController> logger, IMyService _myService)
{
_logger = logger;
_myService = myService;
}
public MyMethod()
{
try
{
var x = _myService.DoThis();
}
catch (Exception ex)
{
_logger.LogError(e, e.Message);
}
}
}
I believe I need to either somehow register Airbrake with ILogger or perhaps create my own logging service.
public class Logging : ILogging
{
public void LogError(Exception e, string message)
{
var airbrake = new AirbrakeNotifier(new AirbrakeConfig
{
ProjectId = // pulled from web.config somehow
ProjectKey = // pulled from web.config somehow
});
var notice = airbrake.BuildNotice(ex);
airbrake.NotifyAsync(notice).Result;
}
}
I have tried using this as starting point: https://github.com/airbrake/sharpbrake/blob/master/docs/asp-net-http-module.md
This is excellent, but I need to extend it somehow to be able to use it within my services and not just the .Web project.
I know there's the ASP.NET module that will automatically capture the errors but I am wanting to manually log when I see fit, and avoid having to call the airbrake client every time I want to log an error.
Is there a way to do this or am I completely misunderstanding how this should be working?
You don't actually need to wire it up as part of the .NET ILogger. I am sure there is a way (probably via OWIN) but you nothing stops you from writing a basic logging service as you would any other service and using that via bog standard DI. The answer was pretty much in the question to begin with.
I have an ASP.Net Web Forms app where I just integrated Sustainsys.Saml2 library.
I've never used any sort of logging mechanism and I'm trying to figure out how to add or create an ILoggerAdapter for the library stated on their troubleshooting page.
I've decided to use NLog (please feel free to recommend a different one) and either I'm not understanding this well, or am not using the right keyword to search for what I need/want, or their isn't a lot of documentation on it.
Currently, I'm using the HttpModule version of Sustainsys.Saml2. Any other information available upon request.
Any help would be great.
Currently, I'm configuring the Sustainsys.Saml2 library through both web.config and the global.asax files. Here's the class my global.asax calls:
public class Saml2Config {
private static bool _alreadyInitialized;
private static readonly object Lock = new object();
public static void Initialize() {
if (_alreadyInitialized) {
return;
}
lock (Lock) {
if (_alreadyInitialized) {
return;
}
var domain = PageHelper.GetDomainURL(true);
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.EntityId.Id = $"{domain}/federation/Saml2";
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.ModulePath = "/federation/Saml2";
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.ReturnUrl = new Uri($"{domain}/mybarry");
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.PublicOrigin = new Uri($"{domain}");
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.Logger = new NullLoggerAdapter();
_alreadyInitialized = true;
}
}
}
The interface is pretty straightforward
public interface ILoggerAdapter
{
void WriteInformation(string message);
void WriteError(string message, Exception ex);
void WriteVerbose(string message);
}
I would implement it as follows:
public class NLogAdapter : ILoggerAdapter
{
private static Logger Logger = LogManager.GetLogger("Saml2");
public void WriteInformation(string message)
{
Logger.Info(message);
}
public void WriteError(string message, Exception ex)
{
Logger.Error(ex, message);
}
public void WriteVerbose(string message)
{
Logger.Debug(message);
}
}
And finally set it:
Sustainsys.Saml2.Configuration.Options.FromConfiguration.SPOptions.Logger = new NLogAdapter();
The ILoggerAdapter contains methods for different loglevels. Make an adapter class that implements ILoggerAdapter and writes to NLog. Then set SPOptions.Logger to an instance of your adapter class.
If you want an example, you can check out the adapter for Asp.Net Core that logs to the Asp.Net Core logging system and is the default for the Sustainsys.Saml2.AspNetCore2 package: https://github.com/Sustainsys/Saml2/blob/master/Sustainsys.Saml2.AspNetCore2/AspNetCoreLoggerAdapter.cs
For the Sustainsys.Saml2.HttpModule library the default is the NullLoggerAdapter which simply discards any logs. Only reason to use it is to not have to nullcheck the Logger property everywhere it is used (that code was written before the ?. syntax was introduced.)
I wanted to know how to inject ILogger into a function in a ASP.NET Core app that's called by a Java client through Thrift.
So a high level code demo of what I want to do:
// ExecuteRequest is called by java client through Thrift
public class ThriftLayer
{
...
public string ExecuteRequest(...params)
{
...
var result = RequestFunc1(...params);
...do processing
return result;
}
...
}
// Contains request functions called by ExecuteRequest
public class ServerRequestHandler
{
...
public string RequestFunc1(...params)
{
return TaskFunc1(...params);
}
....
}
// Functions in this class are called by both the Thrift layer(called by ServerRequestHandler) as well as a Console application
// In Console applications, we can inject the ILogger at Startup - No issues there.
public class TaskFunctions
{
private readonly ILogger<TaskFunctions> _logger;
public TaskFunctions(ILogger<TaskFunctions> logger)
{
_logger = logger;
}
public string TaskFunc1(...params)
{
_logger.logInfo("<log message>");
...do processing
return stringResult;
}
}
So I wanted to know how can I inject ILogger into TaskFunctions while calling from Thrift?
The accepted answer from this question on StackOverflow will help you.
You need to build a ServiceCollection outside of the ASP.NET Core's Startup class.
the MVC part of your application will add those services in Startup.ConfigureServices method
the other part of your application will need to build and then use the service provider as such var taskFunctionsWithInjected = ActivatorUtilities.CreateInstance<TaskFunctions>(serviceProvider); in order to get the dependencies
I'm building a very small web API using .NET Framework 4.5.2. In Visual Studio, I started the project as Empty, with references for Web API 2. I wanted to make use of Dependency Injection, so I did everything as explained in this tutorial by Microsoft and included Unity in my project. Everything works, the API acts as intended and sends the expected responses, however... In the Visual Studio Output tab, I noticed many exceptions being silently raised ("Eccezione generata" means "Exception raised") right after starting the API:
This bugs me quite a bit. I'm concerned about the API stability and reliability. Following is the code involved in the DI process.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// As explained in the tutorial
var container = new UnityContainer();
container.RegisterType<IDecrypter, Decrypter>(new HierarchicalLifetimeManager());
container.RegisterType<IMyRepository, MyRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Routing follows...
}
}
The Decrypter used for internal cryptography.
public interface IDecrypter
{
string Decrypt(string input);
}
public class Decrypter : IDecrypter
{
public string Decrypt(string input) { /* ... */ }
}
The Repository used to access the database.
public interface IMyRepository
{
// Interface Methods...
}
public abstract class BaseRepository
{
private readonly IDecrypter Decrypter;
public BaseRepository(IDecrypter decrypter)
{
Decrypter = decrypter;
// More code...
}
// More code...
}
public class MyRepository : BaseRepository, IMyRepository
{
public MyRepository(IDecrypter decrypter) : base(decrypter)
{ }
// Implementations of the interface methods...
}
The API one and only Controller:
public class MyController : ApiController
{
private readonly IMyRepository myRepository;
public MyController(IMyRepository _myRepository)
{
myRepository = _myRepository;
}
}
Does anyone know what is going on?
I'm trying to use Abp.Quartz for scheduling jobs.
Working with net core 2.2, abp 4.5
I did everything like in docs here
https://aspnetboilerplate.com/Pages/Documents/Quartz-Integration , only resolved it in PostInitialize method.
At the end I tried exactly the same as in docs (start scheduler from controller).
But it not worked too. Job is not starting.
namespace Cloud
{
[DependsOn(typeof(AbpZeroCoreModule),
typeof(AbpQuartzModule))]
public class CloudCoreModule : AbpModule
{
public override void PreInitialize()
{
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(CloudCoreModule)
.GetAssembly());
}
public override void PostInitialize()
{
IocManager.Resolve<IQuartzScheduleJobManager>().ScheduleAsync<ApiRequestQueues.ApiRequestProcessor>(
job =>
{
job
.WithIdentity("RevolutApiProcessor")
.WithDescription("A job witch processing request front");
},
trigger =>
{
trigger
.StartNow()
.WithSimpleSchedule(
schedule =>
{
schedule
.RepeatForever()
.WithIntervalInSeconds(5)
.Build();
});
});
}
}
}
and here is class ApiRequestProcessor
public class ApiRequestProcessor : JobBase, ITransientDependency
{
public override async Task Execute(IJobExecutionContext context)
{
//some work
}
}
Better late to the party than never.
I've managed to get this working, though without Abp.Quartz package. If you're able to use the standard Quartz package, you can use the following steps:
Define and set up your jobs as normal in Startup.cs
Ensure that your class implements both IJob for Quartz to be happy, and ITransientDependency for ASP.NET Boilerplate to be happy
Very important, if your job code uses DbContext in any way, you need to ensure that the [UnitOfWork] decorator is on your job class (which is anyway important to ensure your jobs run atomically and do not affect any other transactions which may be occurring on your server)
In short, a working bare-bones job class might look like this:
using System;
using Quartz;
namespace MyProject.MyJobService
{
[UnitOfWork]
public class SimpleJob : IJob, ITransientDependency
{
public async Task Execute(IJobExecutionContext context)
{
Console.WriteLine("Hello from quartz job!");
}
}
}
More information and discussion can be found here (also how I finally arrived at this solution): https://github.com/aspnetboilerplate/aspnetboilerplate/issues/3757
When in doubt, carefully read what Quartz is telling you in the application output - it usually gives clues as to what is wrong, but I'm confident my solution will work for you 😊