I have a question about KestrelServerOptions.ApplicationSchedulingMode in .NET Core 2.2
public class KestrelServerOptions
{
public SchedulingMode ApplicationSchedulingMode { get; set; }
}
public enum SchedulingMode
{
// Use the transport provided ApplicationScheduler
Default,
// Use the thread pool
ThreadPool,
// Run on the "current" thread
Inline
}
For socket transport, is Default the same as ThreadPool?
For libuv transport, Does Default mean using libuv's own native thread?
Related
How do I change the timeout duration in logic apps web hook and also in chalkboard API.
The error message I get is.
"message": "Http request failed: the server did not respond within the timeout limit. Please see logic app limits at https://aka.ms/logic-apps-limits-and-config#http-limits"
You can refer to Perform long-running tasks with the webhook action pattern.
After understanding the webhook pattern, you need to design some code, you can refer to the following sample:
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using System.Threading;
using System.Net.Http;
using System;
namespace HttpToQueueWebhook
{
public static class HttpTrigger
{
[FunctionName("HttpTrigger")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequest req,
TraceWriter log,
[Queue("process")]out ProcessRequest process)
{
log.Info("Webhook request from Logic Apps received.");
string requestBody = new StreamReader(req.Body).ReadToEnd();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string callbackUrl = data?.callbackUrl;
//This will drop a message in a queue that QueueTrigger will pick up
process = new ProcessRequest { callbackUrl = callbackUrl, data = "some data" };
return new AcceptedResult();
}
public static HttpClient client = new HttpClient();
/// <summary>
/// Queue trigger function to pick up item and do long work. Will then invoke
/// the callback URL to have logic app continue
/// </summary>
[FunctionName("QueueTrigger")]
public static void Run([QueueTrigger("process")]ProcessRequest item, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {item.data}");
//Thread.Sleep(TimeSpan.FromMinutes(3));
//ProcessResponse result = new ProcessResponse { data = "some result data" };
//handle your business here.
client.PostAsJsonAsync<ProcessResponse>(item.callbackUrl, result);
}
}
public class ProcessRequest
{
public string callbackUrl { get; set; }
public string data { get; set; }
}
public class ProcessResponse
{
public string data { get; set; }
}
}
The above code will first save your callbackUrl and the passed data to the queue, and then return the result of 202 to the logic app.
The QueueTrigger function will be triggered, and you can handle your business here.
You can call your http function like this in Azure logic app:
This solution can help you solve the http timeout problem. For more details, you can refer to this article.
I would like to make a contained libraries/services in the new .NET Core world. Basically I have several SASS products:
ServiceProduct1: has a repository layer that the UI/Composistion root layer doesn't need to know about.
ServiceProduct2: has a repository layer that the UI/Composistion root layer doesn't need to know about. Has an Email service in it as well.
These two service products are used in multiple applications, but the consuming application has to know to bind the interfaces hidden in the repository. Also the Email service uses Dependency Injection and it has to be
bound in the consuming application, even though it is used by a service.
Prior to .NET Core I would have used Recursion to search the dlls for things to bind:
public static IKernel LoadAssemblies(IKernel kernel)
{
var type = typeof(INinjectDependency);
var dependencies = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetMatchingTypesInAssembly(y => type.IsAssignableFrom(y) && y.IsClass));
var assemblies = dependencies.Select(Assembly.GetAssembly).Distinct();
kernel.Load(assemblies);
return kernel;
}
Then in the consumed services you would do all your binding.
I am not using Ninject any longer but the concept is the same. Now unless you swap to publish the dll's on build, you cannot use this approach anymore. I do not want to publish my dll's.
Is there another way to handle this?
A lot of the documentation floating around points specifically to the implementation of ASP.NET Core, so I can see why this is confusing. The answer is rather simple. If your services are full executables, i.e.; when compiled they generate an *.exe then you need to wire-up you services at startup - somewhere near the main entry point. If your service is simply a *.dll, then you must have a host application (executable) that wires up the dependencies for you - and then hands you the service collection, such that you can construct an IServiceProvider.
Here is a great article on Dependency Injection with .NET Core. Here is the example of how you would achieve this:
public class Host
{
public static void Main()
{
IServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var application = new Application(serviceCollection);
// Run
// ...
}
static void ConfigureServices(
IServiceCollection serviceCollection)
{
ILoggerFactory loggerFactory = new Logging.LoggerFactory();
serviceCollection.AddInstance<ILoggerFactory>(loggerFactory);
}
}
There are some standard naming conventions here, notice the ConfigureServices. Then the Application object is defined as such:
public class Application
{
public IServiceProvider Services { get; set; }
public ILogger Logger { get; set; }
public Application(IServiceCollection serviceCollection)
{
ConfigureServices(serviceCollection);
// The service-provider is not built until all services are configured.
Services = serviceCollection.BuildServiceProvider();
Logger =
Services.GetRequiredService<ILoggerFactory>()
.CreateLogger<Application>();
Logger.LogInformation("Application created successfully.");
}
public void MakePayment(PaymentDetails paymentDetails)
{
Logger.LogInformation(
$"Begin making a payment { paymentDetails }");
IPaymentService paymentService =
Services.GetRequiredService<IPaymentService>();
// ...
}
void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<IPaymentService, PaymentService>();
}
}
We can now imagine that the interface and corresponding implementation of the payment service looks something like this:
public class PaymentService: IPaymentService
{
public ILogger Logger { get; }
public PaymentService(ILoggerFactory loggerFactory)
{
Logger = loggerFactory?.CreateLogger<PaymentService>();
if (Logger == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
Logger.LogInformation("PaymentService created");
}
}
Note
This does not have to be an ASP.NET Core application.
Due to performance issue , I have added the publishing code in thread.
My code is:
public void functionname()
{
----------------
------------
try
{
HttpontextforMailSending gethttpcontextforpublish2 = new HttpontextforMailSending()
{
HttpContextReference = HttpContext.Current,
courseDocument = shortCourseDocument,
createdUser = new User(0)
};
Thread t2 = new Thread(PublishDocument);
t2.Start(gethttpcontextforpublish2);
}
catch { }
-------------
-----------
}
private void PublishDocument(object input)
{
HttpontextforMailSending httpcontextformail = (HttpontextforMailSending)input;
Document course = httpcontextformail.courseDocument;
User createduser = httpcontextformail.createdUser;
if (course != null && createduser != null)
{
course.Publish(createduser);
umbraco.library.UpdateDocumentCache(course.Id);
}
}
public class HttpontextforMailSending
{
public HttpContext HttpContextReference { get; set; }
public Document courseDocument { get; set; }
public User createdUser { get; set; }
}
But I get Object reference not set to an instance of an object" error on "course.Publish(createduser);
The Umbraco version is 4.8.1.
May be this error is due to course.HttpContext. It has null value.
However when I set it as course.HttpContext = httpcontextformail.HttpContextReference; it shows a warning
"umbraco.cms.businesslogic.web.document.HttpContext is obsolete. Do not use this. GethttpContextvia regular ASP.Net methods instead.
When I debug this code, I get HttpContext on httpcontextformail.HttpContextReference.
But after executing course.HttpContext = httpcontextformail.HttpContextReference;, course.HttpContext still have null value.
Please help me
Thanks
Umbraco expects to be used within a web request and therefore the API will not work if called outside of a web request in another application etc.
If you want to execute some something using the Umbraco API externally then you will need to use Umbraco Base (or similar) so that the API has the needed HttpContext.
Umbraco Base is a RESTlike system for allowing the execution of queries or code via defined URLs within an Umbraco context.
Problem: user operates over some entity in a domain. The last one changes its status so that user recieves e-mail notifications (using smtp server) repeatedly until the given time.
So I need to fire an event somehow.
What are the alternative ways to do that? I know there're no events in ASP.NET MVC framework.
Thanks!
You can use my Inversion Of Control container which has built in support for in-process domain events:
Subscribing
Subscribing is easy. Simply let any class implement IHandlerOf:
[Component]
public class ReplyEmailNotification : IHandlerOf<ReplyPosted>
{
ISmtpClient _client;
IUserQueries _userQueries;
public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
{
_client = client;
_userQueries = userQueries;
}
public void Invoke(ReplyPosted e)
{
var user = _userQueries.Get(e.PosterId);
_client.Send(new MailMessage(user.Email, "bla bla"));
}
}
Dispatching
Domain events are dispatched using the DomainEvent class. The actual domain event can be any class, there are no restrictions. I do however recommend that you treat them as DTO's.
public class UserCreated
{
public UserCreated(string id, string displayName)
{
}
}
public class UserService
{
public void Create(string displayName)
{
//create user
// [...]
// fire the event.
DomainEvent.Publish(new UserCreated(user.Id, user.DisplayName));
}
}
The code is from my article: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
ASP.NET MVC3 installation:
Use package manager console: install-package griffin.container.mvc3
Follow these instructions: http://griffinframework.net/docs/container/mvc3/
I'm building a mvc webapp that shares model objects with an existing winforms app. I'm introducing VAB validation into it. One of the items I need to validate is an int that can be one of x levels.
I've written a LevelValidator, but it needs to have the levels accessible.
Regarding the new call in this code, it looks like I should inject the LevelValidator instead of Levels?
Other ways?
public class LevelValidatorAttribute : ValueValidatorAttribute
{
protected override Microsoft.Practices.EnterpriseLibrary.Validation.Validator DoCreateValidator(Type targetType)
{
LevelValidator validator = new LevelValidator();
validator.Levels = this.Levels;
return validator;
}
[Dependency]
public Levels Levels { get; set; }
}
You can't use dependency injection on attributes, because attributes are not controlled and created by a dependency injection framework, but controlled by the CLR itself. Try having a design were your attribute does not need dependency injection.
If all fails, you can use the Service Locator pattern inside the LevelValidator (best to leave the attribute allone) and make a call to the unity container from within the LevelValidator class. For this to work, you need to have a static field that holds the container. For instance:
public class LevelValidator : Validator
{
public static UnityContainer Container { get; set; }
public LevelValidator()
{
this.Levels = Container.Resolve<Levels>();
}
public Levels Levels { get; set; }
}
In the startup path of your application you need to set this static Container property, as follows:
public void Main()
{
var container = new UnityContainer();
// configure it
LevelValidator.Container = container;
}
This solution is far from ideal and should be prevented in most cases. However, the creation of the attribute and the LevelValidator is outside the control of Unity.