i'm building a class library project using c# to scale/resize images,the project only has one class with only one public static function with 2 parameters now the code is working fine and perfect so its not the issue here.
now, how can i execute this function directly from url?
ex:my project called: myDLL.dll
how to do this:
img src="/myDLL.dll?image=/images/pic1.png&width=200"
so this execute my function and pass width and image as parameters
i know how to add iis handler to execute DLL from browser..but i dont know how to make this :/myDLL.dll?image=/images/pic1.png&width=200 run my function
plz help
Yes, you can.
HTTP Handler
public class Class1 : IHttpHandler
{
public bool IsReusable => false;
public void ProcessRequest(HttpContext context)
{
Assembly ass = Assembly.LoadFile(context.Request.PhysicalPath);
Type[] assemblyTypes = ass.GetTypes();
for (int j = 0; j < assemblyTypes.Length; j++)
{
if (assemblyTypes[j].Name == "WebDLL")
{
object o = Activator.CreateInstance(assemblyTypes[j]);
MethodInfo mi = assemblyTypes[j].GetMethod("ProcessRequest");
mi.Invoke(o, new object[] { context });
}
}
}
}
DLL
public class WebDLL
{
public void ProcessRequest(HttpContext context)
{
context.Response.Write("Hello World!");
}
}
It will output Hello World!
Related
I am having trouble figuring out how I can use the structured logging, when NLog is in a wrapper class. I have an asp.net webapp that calls my nlog wrapper class.
It works fine for regular logging ex. logger.Info("Gets to here.") but i can't get it to work for structured logging calls ex. logger.Info("This is structured logging entry #{param1}", new {Status = "processing"})
This is my Wrapper class for NLog(EventLog.LogManager):
public static void Info(params object[] args)
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
Logger.Log(LogLevel.Info, args);
//This is what I've tried to no avail.
//var ci = new CultureInfo("en-US");
//LogEventInfo le = LogEventInfo.Create(LogLevel.Info, Logger.Name, ci, args);
//le.Parameters = args;
//string test = le.FormattedMessage;
//string test1 = string.Format(le.Parameters[0].ToString(), le.Parameters[1].ToString());
//Logger.Log(typeof(LogManager), le);
}
This is my asp.net application that calls the above method:
public ActionResult Index()
{
EventLog.LogManager.Info("Test #{param1}", new { OrderId = 2, Status = "Processing" });
return View();
}
If anyone can point me in the right direction, it would be greatly appreciated. Thank you in advance.
Try changing into this:
namespace EventLog
{
public static class LogManager
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
public static void Info(string message, params object[] args)
{
Logger.Info(message, args);
}
}
}
I have a simple console application which uses Autofac as IoC container.
class Program
{
static IContainer container;
static void Main(string[] args)
{
container = Configure();
Run();
}
private static void Run()
{
using (var scope = container.BeginLifetimeScope())
{
var t = scope.Resolve<ITest1>();
var s = t.TestMethod1("");
Console.WriteLine(s);
}
}
private static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass1>()
.As<ITest1>();
builder.RegisterType<TestClass2>()
.As<ITest2>();
return builder.Build();
}
}
The application calls the method "TestMethod1" in "TestClass1".
public interface ITest1
{
string TestMethod1(string s);
}
public class TestClass1 : ITest1
{
ITest2 f;
public TestClass1(Func<ITest2> test2Factory)
{
f = test2Factory();
}
public string TestMethod1(string s)
{
var r = string.Empty;
r = f.TestMethod2(s);
r += ":TestMethod1";
return r;
}
}
TestClass1 has a dependency on TestClass2 which declares a delegate factory for Autofac to use with the TestClass1 constructor.
public interface ITest2
{
string TestMethod2(string s);
}
public class TestClass2 : ITest2
{
public delegate TestClass2 Factory();
public virtual string TestMethod2(string s)
{
return ":TestMethod2";
}
}
This all works as expected - Autofac resolves the TestClass2 dependency, and I get the output ":TestMethod2:TestMethod1".
Now I want to mock TestClass2 using Moq and the Autofac.Extras.Moq extensions. I add the following method to the console application, and call it from the Program Main method.
private static void Test()
{
using (var mock = AutoMock.GetLoose())
{
mock.Mock<TestClass2>()
.Setup(t => t.TestMethod2(""))
.Returns(":NOT_TEST_METHOD2");
var s = mock.Create<TestClass1>();
var r = s.TestMethod1("cheese");
Console.WriteLine(r);
}
}
Now I get the output ":TestMethod1" when I expect ":NOT_TEST_METHOD2:TestMethod1". It seems the mock has not been called. This is confirmed when I step through the code.
I have also tried resolving the mock using mock.Provide(), as has been suggested elsewhere (see below). Still no luck.
var wc = Moq.Mock.Of<TestClass2>(f => f.TestMethod2("") == ":NOT_TEST_METHOD2");
Func<string, ITest2> factory = x => wc;
mock.Provide(factory);
This seems like a really simple scenario but I've not found a working answer anywhere. Can anyone see what I'm doing wrong?
Thanks for any help!
I don't use the AutoMock support, but I do know my Autofac, so I can give it a shot.
It looks like TestClass1 takes an ITest2 and not a TestClass2 in its constructor, I'm guessing if you switched to this:
mock.Mock<ITest2>()
.Setup(t => t.TestMethod2(""))
.Returns(":NOT_TEST_METHOD2");
...then it might work.
Thanks Travis. Your suggestion didn't work for me, but it made me think about the issue differently and taking a step back made me realise I was looking for a complex solution where one wasn't required. Namely, that only Moq was needed, Autofac AutoMock extensions were not. The following code worked:
private static void Test()
{
Func<ITest2> func = () =>
{
var x = new Mock<ITest2>();
x.Setup(t => t.TestMethod2("")).Returns(":NOT_TEST_METHOD2");
return x.Object;
};
var s = new TestClass1(func);
var r = s.TestMethod1("");
}
The question was answered by this post Using Moq to Mock a Func<> constructor parameter and Verify it was called twice.
I'm trying build out our logging framework using EntLib Logging and use attribute to indicate which class/method should be logged. So I think Interception would be a good choice. I'm a super noob to Ninject and Interception and I's following the tutorial at Innovatian Software on how to use interception via attributes. But when I run the app, BeforeInvoke and AfterInvoke was never called. Help Please, Thank You!
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Castle.Core;
using Ninject;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Attributes;
using Ninject.Extensions.Interception.Request;
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<ObjectWithMethodInterceptor>().ToSelf();
var test= kernel.Get<ObjectWithMethodInterceptor>();
test.Foo();
test.Bar();
Console.ReadLine();
}
}
public class TraceLogAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<TimingInterceptor>();
}
}
public class TimingInterceptor : SimpleInterceptor
{
readonly Stopwatch _stopwatch = new Stopwatch();
protected override void BeforeInvoke(IInvocation invocation)
{
Console.WriteLine("Before Invoke");
_stopwatch.Start();
}
protected override void AfterInvoke(IInvocation invocation)
{
Console.WriteLine("After Invoke");
_stopwatch.Stop();
string message = string.Format("Execution of {0} took {1}.",
invocation.Request.Method,
_stopwatch.Elapsed);
Console.WriteLine(message);
_stopwatch.Reset();
}
}
public class ObjectWithMethodInterceptor
{
[TraceLog] // intercepted
public virtual void Foo()
{
Console.WriteLine("Foo - User Code");
}
// not intercepted
public virtual void Bar()
{
Console.WriteLine("Bar - User Code");
}
}
I figured it out, I missed the part where I've to disable auto module loading and manually load the DynamicProxy2Module to the kernel. Here's the change to the code:
//var kernel = new StandardKernel(); //Automatic Module Loading doesn't work
var kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false }, new DynamicProxy2Module());
Hope this help someone else.
Does anybody know of a tool, script, package, whatever that I can use to visit all pages in an ASP.NET Webforms web application project? (we aren't using any MVC functionality)
Preferably, I would like to be able to generate a list of URLs to hit, edit the list so I can add some query string params, hit all the pages in the list, and collect HTTP response codes: (200, 404, 500, 301, whatever).
Design time
Instead of using string literals for URLs in your application, define Url() methods in each page class like this:
public static string Url() { get { return "~/this_page.aspx"; } }
public static string Url(int ID) { get { return "~/this_page.aspx?id=" + ID; } }
Or list all URLs in a static class
public static class URL {
public static string Login() { get { return "~/login.aspx"; } }
public static string DisplayRecord(int recordID)
{ get { return "~/display.aspx?id=" + recordID; } }
Runtime
Use a web testing framework to crawl all links and edit the result. I blogged about one possible solution using Selenium.
I made a WinForms application that gets the pages that can be accessed from the .csproject and can open them by clicking a button.
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
namespace OpenAllPages
{
public partial class Form1 : Form
{
public static IList<string> Pages;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string xmlstring = ReadXml("TaskManager.csproj");
Pages = ParseAllPages(xmlstring);
pagesListBox.DataSource = Pages;
}
private string ReadXml(string location)
{
try
{
var myFile = new StreamReader(location);
string myString = myFile.ReadToEnd();
myFile.Close();
return myString;
}
catch (Exception e)
{
MessageBox.Show(String.Format("An error occurred: '{0}'", e.Message));
}
return null;
}
private IList<string> ParseAllPages(string xmlstring)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlstring);
XPathNavigator nav = xmlDoc.DocumentElement.CreateNavigator();
XmlNamespaceManager manager = new XmlNamespaceManager(nav.NameTable);
manager.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
var elements = nav.Select("x:ItemGroup/x:Content", manager);
var pageList = new List<string>();
while (elements.MoveNext())
{
var page = elements.Current.GetAttribute("Include", "");
if (page.EndsWith(".aspx"))
pageList.Add(page);
}
return pageList as IList<string>;
}
private string AddPagePrefix(string page)
{
return "http://localhost:8080/" + page;
}
private void openAllButton_Click(object sender, EventArgs e)
{
foreach (string page in Pages)
System.Diagnostics.Process.Start("chrome.exe", AddPagePrefix(page));
}
}
}
Here is a link to the code
You need to place the project file which contains the pages you want to open in the OpenAllPages project and set it's Copy to Output property to "Copy if newer".
I Form1_Load change TaskManager.csproj to the name of your project file.
And in:
System.Diagnostics.Process.Start("chrome.exe", AddPagePrefix(page));
rename parameter to the executable of the browser you are using.
I am trying to wire up dependency injection with Windsor to standard asp.net web forms. I think I have achieved this using a HttpModule and a CustomAttribute (code shown below), although the solution seems a little clunky and was wondering if there is a better supported solution out of the box with Windsor?
There are several files all shown together here
// index.aspx.cs
public partial class IndexPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Logger.Write("page loading");
}
[Inject]
public ILogger Logger { get; set; }
}
// WindsorHttpModule.cs
public class WindsorHttpModule : IHttpModule
{
private HttpApplication _application;
private IoCProvider _iocProvider;
public void Init(HttpApplication context)
{
_application = context;
_iocProvider = context as IoCProvider;
if(_iocProvider == null)
{
throw new InvalidOperationException("Application must implement IoCProvider");
}
_application.PreRequestHandlerExecute += InitiateWindsor;
}
private void InitiateWindsor(object sender, System.EventArgs e)
{
Page currentPage = _application.Context.CurrentHandler as Page;
if(currentPage != null)
{
InjectPropertiesOn(currentPage);
currentPage.InitComplete += delegate { InjectUserControls(currentPage); };
}
}
private void InjectUserControls(Control parent)
{
if(parent.Controls != null)
{
foreach (Control control in parent.Controls)
{
if(control is UserControl)
{
InjectPropertiesOn(control);
}
InjectUserControls(control);
}
}
}
private void InjectPropertiesOn(object currentPage)
{
PropertyInfo[] properties = currentPage.GetType().GetProperties();
foreach(PropertyInfo property in properties)
{
object[] attributes = property.GetCustomAttributes(typeof (InjectAttribute), false);
if(attributes != null && attributes.Length > 0)
{
object valueToInject = _iocProvider.Container.Resolve(property.PropertyType);
property.SetValue(currentPage, valueToInject, null);
}
}
}
}
// Global.asax.cs
public class Global : System.Web.HttpApplication, IoCProvider
{
private IWindsorContainer _container;
public override void Init()
{
base.Init();
InitializeIoC();
}
private void InitializeIoC()
{
_container = new WindsorContainer();
_container.AddComponent<ILogger, Logger>();
}
public IWindsorContainer Container
{
get { return _container; }
}
}
public interface IoCProvider
{
IWindsorContainer Container { get; }
}
I think you're basically on the right track - If you have not already I would suggest taking a look at Rhino Igloo, an WebForms MVC framework, Here's a good blog post on this and the source is here - Ayende (the Author of Rhino Igloo) tackles the issue of using Windsor with webforms quite well in this project/library.
I would cache the reflection info if you're going to inject the entire nested set of controls, that could end up being a bit of a performance hog I suspect.
Last of all spring.net approaches this in a more configuration-oriented way, but it might be worth taking a look at their implementation - here's a good reference blog post on this.
Here's a modified version of the OP's code that (i) caches injected properties to avoid repeated reflection calls, (ii) releases all resolved components, (iii) encapsulates container access so as not to expose implementation.
// global.asax.cs
public class Global : HttpApplication
{
private static IWindsorContainer _container;
protected void Application_Start(object sender, EventArgs e)
{
_container = new WindsorContainer();
_container.Install(FromAssembly.This());
}
internal static object Resolve(Type type)
{
return _container.Resolve(type);
}
internal static void Release(object component)
{
_container.Release(component);
}
//...
}
// WindsorHttpModule.cs
public class WindsorHttpModule : IHttpModule
{
// cache the properties to inject for each page
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> InjectedProperties = new ConcurrentDictionary<Type, PropertyInfo[]>();
private HttpApplication _context;
public void Init(HttpApplication context)
{
_context = context;
_context.PreRequestHandlerExecute += InjectProperties;
_context.EndRequest += ReleaseComponents;
}
private void InjectProperties(object sender, EventArgs e)
{
var currentPage = _context.Context.CurrentHandler as Page;
if (currentPage != null)
{
InjectProperties(currentPage);
currentPage.InitComplete += delegate { InjectUserControls(currentPage); };
}
}
private void InjectUserControls(Control parent)
{
foreach (Control control in parent.Controls)
{
if (control is UserControl)
{
InjectProperties(control);
}
InjectUserControls(control);
}
}
private void InjectProperties(Control control)
{
ResolvedComponents = new List<object>();
var pageType = control.GetType();
PropertyInfo[] properties;
if (!InjectedProperties.TryGetValue(pageType, out properties))
{
properties = control.GetType().GetProperties()
.Where(p => p.GetCustomAttributes(typeof(InjectAttribute), false).Length > 0)
.ToArray();
InjectedProperties.TryAdd(pageType, properties);
}
foreach (var property in properties)
{
var component = Global.Resolve(property.PropertyType);
property.SetValue(control, component, null);
ResolvedComponents.Add(component);
}
}
private void ReleaseComponents(object sender, EventArgs e)
{
var resolvedComponents = ResolvedComponents;
if (resolvedComponents != null)
{
foreach (var component in ResolvedComponents)
{
Global.Release(component);
}
}
}
private List<object> ResolvedComponents
{
get { return (List<object>)HttpContext.Current.Items["ResolvedComponents"]; }
set { HttpContext.Current.Items["ResolvedComponents"] = value; }
}
public void Dispose()
{ }
}
I've recently started at a company where there are a lot of legacy webform apps, so this looks to be a real interesting approach, and could offer a way forward if we wanted to add DI to existing web pages, thanks.
One point I noticed is that the Injection method uses the container.Resolve to explicitly resolve components, therefore I think we may need to do a container.Release on the components when the Page Unloads.
If we have transient components and don't do this then we may face memory leakages. Not sure how components with Per Web Request lifestyles would behave (i.e. would Windsor pick them up at the end of the web request, even though we explicitly resolved them) but here too may want to play safe.
Therefore the module may need to be extended to keep track of the components that it resolves and release them so that Windsor knows when to clean up.
One thing that was missing from the accepted answers was the fact that the http module needs to be registered in the web.config file (depending on the application) before the module will actually resolve the dependencies on the code-behind pages. What you need is :
<system.webServer>
<modules>
<add name="ClassNameForHttpModuleHere" type="NamespaceForClass"/>
</modules>
</system.webServer>
Other than that the accepted solutions worked like a charm.
Reference to the Microsoft website for adding http modules: https://msdn.microsoft.com/en-us/library/ms227673.aspx
Rather than doing it like this, you could also use a type resolver directly with something like:
ILogger Logger = ResolveType.Of<ILogger>();