Is it possible to use automapper in a console application?
Its Getting Started Page suggests the bootstrapper class be called from Application start up, but there are no further details about a class to add and call from Main().
How do I go about using this in a simple console app?
You can initialize Automapper in the console startup, there's no limitations; the Application_start is the startup place for a web program in .net/iis, ie code that is called only once. Any configuration that you must call at the start of a web project goes in this method.
edit for comment: if you don't want to create your mappings on the fly, but would rather have a place to initialize all your mappings, just create a function called InitializeAutomapper and make the Mapper.Configure<X, Y> calls in here. Then in your Main() method, just call the function. There are lots of ways to handle configuration, but this is the simpler way to handle it.
code sample
class Program
{
static void Main(string[] args)
{
// the app is starting here
InitializeAutomapper();
// we're configured, let's go!
DoStuff();
}
static void InitializeAutomapper()
{
AutoMapper.Mapper.CreateMap<TypeA, TypeB>();
AutoMapper.Mapper.CreateMap<TypeC, TypeD>();
AutoMapper.Mapper.CreateMap<TypeE, TypeF>();
}
}
I know that this is an old question, but if you found this I want to add an update: Automaper does not allow static initialization anymore.
You can check more here
Below, I'm providing a full example of how to use it on a console app. Hope this might be helpful for someone in the future.
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<MyClass, MyClassDTO>();
});
IMapper mapper = config.CreateMapper();
var myClass = new MyClass(){
Id = 10,
Name = "Test"
};
var dst = mapper.Map<MyClass, MyClassDTO>(myClass);
Console.WriteLine(dst.Id);
}
}
class MyClass
{
public int Id {get;set;}
public string Name {get;set;}
}
public class MyClassDTO
{
public int Id {get;set;}
public string Name {get;set;}
}
Do not forget to include using AutoMapper;
Yes, but it appears to have a dependency on System.Web, which must be included too.
(See Mysterious disappearing reference for more details)
Related
How can I create a global variable in an ASP.NET Core Web API application? In ASP.NET MVC, I could do it like:
Application["<variableName>"] = <value>
I tried the same in my web API application, but was unable to find an equivalent for this. I saw some solutions which suggested me to store the data appsettings.json, but since the data I want to store in the global variable is not static, I cannot use that setup. I need to set different data during runtime. How can I do that? Please help me.
We could use Singleton_pattern , creating an Application static object in .net core.
we can also try to use Depend Injection, register a singleton object as below in your code.
Writing a property ConcurrentDictionary in ApplicationInstance class.
public class ApplicationInstance {
public ConcurrentDictionary<string,object> Application { get; } = new ConcurrentDictionary<string, object>();
}
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<ApplicationInstance>();
}
Then we might use this object
public class HomeController : ControllerBase
{
private readonly ApplicationInstance _application;
public HomeController(ApplicationInstance application)
{
this._application = application;
}
//use _application["test"] instance in your code
}
I would use ConcurrentDictionary to help us avoid racing-condition which will be happened on multiple-thread accessing the same object concurrently.
somewhere in project
public static class Config{
public static Dictionary<string,string> Application = new Dictionary<string,string>();
}
elsewhere
Config.Application["froop"] = "noodle";
of course you will have to deal with race conditions, etc
First of all thank you all for finding some time to help me. I took #pm100's solution and made a slight modification to suit my purpose. I could not use it directly as I am using SonarLint, and it had some issues, so I used a KeyValuePair instead of Dictionary like this:
public static class GlobalData
{
public static KeyValuePair<string,object> Application { get; set; }
}
and I used it in my code like:
string value = GlobalData.Application.Value
and luckily it works without any issue.
In my CLI Main I need a object of my MonDbBusinessComponent class.
I wrote the code below, but my object is still null.
What's wrong? How to do it right?
public static IMonDbBusinessComponent monDbBusinessComponent { get; set; }
static void Main(string[] args)
{
var collection = new ServiceCollection();
collection.AddScoped<IMonDbRepository, MonDbRepository>();
ServiceProvider appServiceProvider = GetServiceProvider();
monDbBusinessComponent = appServiceProvider.GetService<IMonDbBusinessComponent>();
you never registered your IMonDbBusinessComponent.
collection.AddScoped<IMonDbBusinessComponent, MonDbBusinessComponent>();
I'm sorry, it was not possible to see in my published coded. The BusinessComponent uses Repository and first I needed to register the Repository with it's arguments and then register the BusinessComponent.
Also at the BusinessComonent I needed to use the Interface instead of the class.
public MonDbBusinessComponent(IMonDbRepository monDbRepository){...}
collection.AddScoped<IMonDbRepository>(ServiceProvider =>
{
string createMetaDataRecordFunctionName = Configurations.Get(LocalConfiguration, "CreateMetaDataRecordFunctionName");
string conDbDataRecordFunctionName = Configurations.Get(LocalConfiguration, "ConDbDataRecordFunctionName");
return new MonDbRepository(metaDataConnection, createMetaDataRecordFunctionName, conDbDataRecordFunctionName);
});
collection.AddScoped<IMonDbBusinessComponent, MonDbBusinessComponent>();
Thanks for all support!
I'm afraid this an XY problem but I cannot find a solution by myself.
To narrow down the problem I create a new C# project with an empty form. Here the program.cs code (updated from the original question to have a very minimal example):
public partial class Form1 : Form
{
private IDisposable webApp;
const string url = "http://localhost:8080";
public Form1()
{
InitializeComponent();
Debug.WriteLine("before");
foo();
webApp = WebApp.Start<Startup>(url);
Debug.WriteLine("after");
foo();
}
private void foo()
{
Debug.WriteLine("foo");
}
}
class Startup
{
public void Configuration(IAppBuilder app) { }
}
Here the (weird) output:
before
foo
after
after
after
foo
foo
foo
Removing the WebApp.Start call leads to the expected output:
before
foo
after
foo
Why?
This is happening because internally Debug.Writeline uses a Trace Listener. If you inspect the Trace.Listeners collection before and after the WebApp.Start line, you'll notice that the web app is adding a second trace listener. So your log messages are getting executed once, but are writing to the "log" multiple times, because there are extra listeners.
The application started with a single DefaultTraceListener, then the web app starts a TextWriterTraceListener. You can remove the extra listener by adding this to your configuration:
Trace.Listeners.Remove("HostingTraceListener");
A second option to fix this is to implement your own ITraceOutputFactory:
public class MyFactory: ITraceOutputFactory
{
public TextWriter Create(string outFile)
{
return TextWriter.Null;
}
}
And register it with your web app:
var myFactory = new MyFactory();
var provider = ServicesFactory.Create(fact => fact.AddInstance<ITraceOutputFactory>(myFactory));
WebApp.Start<Startup>(provider, new StartOptions(url)))
I have a method that uses Application variables to get information from an external file. Since Application variables are not used in unit tests, is there a way I can get the Application variables values from my Global.asax file and be able to use them in the test?
This is my test method:
[TestMethod]
public void TestGetCompanyList()
{
var accController = new AccSerController();
CInt cInt = new CInt();
cIn.Iss = "Other";
cIn.Tick = "BK";
var result
= accController.Clist(cIn) as IEnumerable<CList>;
Assert.IsNotNull(result);
}
Use the repository pattern. Your controller shouldn't have any idea about WebConfiguration.
//This defines the stuff that your controller needs (that your repository should contain)
public interface ISiteConfiguration
{
string Setting1 {get; set;}
}
//Use this in your site. Pull configuration from external file
public class WebConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
public WebConfiguration()
{
//Read info from external file here and store in Setting1
Setting1 = File.ReadAllText(HttpContext.Current.Server.MapPath("~/config.txt"));
}
}
//Use this in your unit tests. Manually specify Setting1 as part of "Arrange" step in unit test. You can then use this to test the controller.
public class TestConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
}
I'm using Ninject to perform dependency injection, but there's lots of other libraries out there. I'm going to omit some basic Ninject setup from my answer, because there's plenty of resources out there. But the below code shows how you'd specify in your web application to use WebConfiguration to fulfill the needs of an ISiteConfiguration.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISiteConfiguration>().To<WebConfiguration>();
}
Here's where the magic happens. When an instance of your controller is created in your web application, Ninject will look at the constructor and see that it's asking for ISiteConfiguration. And in your Ninject configuration, you told it to use WebConfiguration when it needs ISiteConfiguration. So Ninject will create a new instance of WebConfiguration and provide (inject) it to your controller.
public class AccountServiceController
{
ISiteConfiguration Config {get; set;}
//This is called constructor injection
public AccountServiceController(ISiteConfiguration config)
{
Config = config;
}
public ActionResult Index()
{
//Now you can use Config without needing to know about ISiteConfiguration's implementation details
//Get settings from Config instead of Application
}
}
You can also use Ninject in unit testing, but here's a simpler demo where we're not using it:
[TestMethod]
public void TestGetCompanyList()
{
//Arrange
var config = new TestConfiguration(){ Setting1 = "mysetting" };
var accountController = new AccountServiceController(config);
}
The result of all this is that you can use your controller's action methods easily for unit testing, because you can use whatever implementation of ISiteConfiguration you want.
I've done the following on some of my tests. Not ideal but it gets the job done.
if (System.Web.HttpContext.Current != null)
{
// Fill your application variable
}
else
{
// Get your data from somewhere else
}
There are two ways of unit testing such scenarios as far as I know.
First one is based on splitting controller function into two: one is controller function itself, another one implements the logic (e.g.: this is the one you test). Example:
Before:
public void MyControllerFunction()
{
var x = Context["variable"];
do-something-with-x;
}
After:
public void MyControllerFunction()
{
var x = Context["variable"];
MyControllerLogic(x);
}
internal void MyControllerLogic(object x)
{
do-something-with-x;
}
And then you test MyControllerLogic() function instead of MyControllerFunction() in unit test
Another methodology is create a surrogate context before invoking unit test.
Example:
var controller = new MyController();
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
controller.Request.Content = new StringContent("{ x: 21 }",
Encoding.Unicode);
controller.Request.Content.Headers.ContentType.MediaType =
"application/json";
Please note, I did not create HttpContext in 2nd example, I'm not sure if it's a requirement to have. You probably should be able to create it in similar way as well as the other variables you use. It's sort of a hack anyway, so treat it as such
I have a Service Bus queue that I want to consume off of. All of the samples I have found recommend writing something like this:
class Program
{
private static String ServiceBusConnectionString = ConfigurationManager.ConnectionStrings["Microsoft.ServiceBus.ConnectionString"].ConnectionString;
static void Main()
{
var jobHostConfiguration = new JobHostConfiguration
{
ServiceBusConnectionString = ServiceBusConnectionString,
};
var jobHost = new JobHost(jobHostConfiguration);
jobHost.RunAndBlock();
}
}
public class QueueItem
{
public String Name;
public Int64 Id;
}
public class Functions
{
public void ProcessQueueItem([ServiceBusTrigger("queue-name")] QueueItem queueItem)
{
// TODO: process queue item
}
}
The problem with the above code is that the queue name is hard coded in my program. I want to be able to get the queue name from configuration like I do with the queue connection string. Unfortunately, attributes can only be passed compile time constants, so I can't pass in some statically initialized string that comes from configuration.
I looked around a bit and was unable to find any other way to setup Service Bus function binding. Is it just not possible?
You can use a custom INameResolver to accomplish what you want.
One of the official samples here covers exactly your scenario. Take a look the ShutdownMonitor function in Functions.cs and then at the ConfigNameResolver class.