i'm trying to work out the best method to perform logging in the application i'm currently developing.
right now, i have a Log table that stores the username, timestamp, action, controller, and a message. when a controller is instantiated, it gets the IoC info through Castle Windsor.
for example, my "Sites" controller is created as follows:
private ISitesRepository siteRepository;
private ILogWriter logWriter;
public SiteController(ISitesRepository siteRepository, ILogWriter logWriter)
{
this.siteRepository = siteRepository;
this.logWriter = logWriter;
}
and the log writer has a function that creates and inserts a log entry (WriteToLog). within the Sites controller's Edit and Create actions, it calls the WriteToLog function.
this is working and doing its job, but my question is- do i really need to set up each controller this way, passing through the ILogWriter interface/repository? it struck me that i could possibly set up a LogController, and just have that do the "heavy lifting" of writing to my logs.
that way, i wouldn't have to mess with the IoC stuff in every other controller. is it possible to execute an action on another controller (for example, a LogController-> WriteLog)? i'm not sure how would that be done without doing a redirect...
Could you pass by an abstract class? This abstract class having a static property referencing you log writer?
something like this
public abstract class BaseController
{
public static ILogWriter Logwriter{get;set;}
public static BaseController
{
Logwriter = YourFactory.GetLogwriter();
}
}
public class YourController:BaseController
{
public YourController(ISitesRepository siteRepository)
{
}
}
Ok, after much head scratching, i think i found an acceptable solution.
I implemented my logging action as a custom action filter as so:
public class LogAction : ActionFilterAttribute, IActionFilter
{
public LogLevel loglevel;
public string message;
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
logWriter.WriteToLog(
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
filterContext.ActionDescriptor.ActionName,
loglevel,
filterContext.HttpContext.Timestamp,
filterContext.HttpContext.User.Identity.Name.ToString(),
message + "(id=" + filterContext.RouteData.Values["id"] + ")");
}
}
but i ran into a wall trying to get the IoC to work in a custom attribute filter. scouring stackoverflow and google searches, i found that it's sort of difficult to do, with talk about using different wrappers, action invokers, etc, which all seemed more complicated than i was really willing to deal with.
trying to learn more about IoC (i'm still very new at this), i found this article,
which really helped point me in the right direction. i added his sealed AppServiceFactory class with my WindsorControllerFactory, and it worked like a charm.
As i said, i'm very new with to MVC and this IoC stuff, so i'm not sure this is an ideal way of handling things- but it seems simple and it works so far. I'd welcome any comments or criticisms on handling it through this method.
UPDATE
Figured out a different way of doing this- created a function in my WebUI project as such:
public static class Loggers
{
public static void WriteLog(ControllerContext controllerContext, LogLevel logLevel, string message)
{
ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
logWriter.WriteToLog(
controllerContext.RouteData.Values["controller"].ToString(),
controllerContext.RouteData.Values["action"].ToString(),
logLevel,
controllerContext.HttpContext.Timestamp,
controllerContext.HttpContext.User.Identity.Name.ToString(),
message);
}
}
now, wherever i want to log something, i can call
Loggers.WriteLog(
this.ControllerContext,
LogLevel.Membership,
"Removed role '" + role + "'" + " from user " + _userService.Get(id).UserName );
to write a record to the log. this gives me a lot more flexibility on my "message" content, and solves the problem of including logging in the global.asax file, which would've been difficult if not impossible using the attribute filters. i'll leave the rest, as it may be of use to someone else, but i think this is the way i'll go on this.
as usual, things are usually simpler in MVC than i original think they will be :)
Related
I'm trying to implement an RSS/Atom feed aggregator in spring-integration and I am primarily using the Java DSL to write my IntegrationFlow. A requirement of this aggregator is that feeds can be added / removed during runtime. That is to say, the feeds are not known at design time.
I found it simple to use the basic Feed.inboundAdapter() with a test url and extract the links out of the feed with a transformer and then pass it on to an outbound-file-adapter to save the links to a file. However, I have gotten very stuck when trying to read the (thousands) of feed urls from an inbound-file-adapter run the file through a FileSplitter and then pass each resulting Message<String> containing the feed url to then register a new Feed.inboundAdapter(). Is this not possible with the Java DSL?
Ideally I would love it if I could do the following:
#Bean
public IntegrationFlow getFeedsFromFile() throws MalformedURLException {
return IntegrationFlows.from(inboundFileChannel(), e -> e.poller(Pollers.fixedDelay(10000)))
.handle(new FileSplitter())
//register new Feed.inboundAdapter(payload.toString()) foreach Message<String> containing feed url coming from FileSplitter
.transform(extractLinkFromFeedEntry())
.handle(appendLinkToFile())
.get();
}
Though after reading through the spring integration java DSL code multiple times (and learning a tonne of stuff along the way) I just can't see that it's possible to do it this way. So... A) is it? B) should it be? C) Suggestions?
It almost feels like I should be able to take the output of .handle(new FileSplitter()) and pass that into .handleWithAdapter(Feed.inboundAdapter(/*stuff here*/)) but the DSL only references outbound-adapters there. Inbound adapters are really just a subclass of AbstractMessageSource and it seems the only place you can specify one of those is as an argument to the IntegrationFlows.from(/*stuff here*/) method.
I would have thought it would be possible to take the input from a file, split it line by line, use that output to register inbound feed adapters, poll those feeds, extract the new links from feeds as they appear and append them to a file. It appears as though it's not.
Is there some clever subclassing I can do to make this work??
Failing that... and I suspect this is going to be the answer, I found the spring integration Dynamic Ftp Channel Resolver Example and this answer on how to adapt it dynamically register stuff for the inbound case...
So is this the way to go? Any help/guidance appreciated. After pouring over the DSL code and reading documentation for days, I think I'll have a go at implementing the dynamic ftp example and adapting it to work with FeedEntryMessageSource... in which case my question is... that dynamic ftp example works with XML configuration, but is it possible to do it with either Java config or the Java DSL?
Update
I've implemented the solution as follows:
#SpringBootApplication
class MonsterFeedApplication {
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext parent = SpringApplication.run(MonsterFeedApplication.class, args);
parent.setId("parent");
String[] feedUrls = {
"https://1nichi.wordpress.com/feed/",
"http://jcmuofficialblog.com/feed/"};
List<ConfigurableApplicationContext> children = new ArrayList<>();
int n = 0;
for(String feedUrl : feedUrls) {
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.setId("child" + ++n);
children.add(child);
child.setParent(parent);
child.register(DynamicFeedAdapter.class);
StandardEnvironment env = new StandardEnvironment();
Properties props = new Properties();
props.setProperty("feed.url", feedUrl);
PropertiesPropertySource pps = new PropertiesPropertySource("feed", props);
env.getPropertySources().addLast(pps);
child.setEnvironment(env);
child.refresh();
}
System.out.println("Press any key to exit...");
System.in.read();
for (ConfigurableApplicationContext child : children) {
child.close();
}
parent.close();
}
#Bean
public IntegrationFlow aggregateFeeds() {
return IntegrationFlows.from("feedChannel")
.transform(extractLinkFromFeed())
.handle(System.out::println)
.get();
}
#Bean
public MessageChannel feedChannel() {
return new DirectChannel();
}
#Bean
public AbstractPayloadTransformer<SyndEntry, String> extractLinkFromFeed() {
return new AbstractPayloadTransformer<SyndEntry, String>() {
#Override
protected String transformPayload(SyndEntry payload) throws Exception {
return payload.getLink();
}
};
}
}
DynamicFeedAdapter.java
#Configuration
#EnableIntegration
public class DynamicFeedAdapter {
#Value("${feed.url}")
public String feedUrl;
#Bean
public static PropertySourcesPlaceholderConfigurer pspc() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public IntegrationFlow feedAdapter() throws MalformedURLException {
URL url = new URL(feedUrl);
return IntegrationFlows
.from(s -> s.feed(url, "feedTest"),
e -> e.poller(p -> p.fixedDelay(10000)))
.channel("feedChannel")
.get();
}
}
And this works IF and only IF I have one of the urls defined in application.properties as feed.url=[insert url here]. Otherwise it fails telling me 'unable to resolve property {feed.url}'. I suspect what is happening there is that the #Beans defined in DynamicFeedAdapter.java all get singletons eagerly initialized, so aside from the beans being manually created in our for loop in the main method (which work fine because they have feed.url property injected) we have a stray singleton that has been eagerly initialized and if there is no feed.url defined in application.properties then it can't resolve the property and everything goes bang. Now from what I know of Spring, I know it should be possible to #Lazy initialize the beans in DynamicFeedAdapter.java so we don't wind up with this one unwanted stray singleton problem-child. The problem is now...if I just mark the feedAdapter() #Lazy then the beans never get initialized. How do I initialize them myself?
Update - problem solved
Without having tested it, I think the problem is that boot is finding
the DynamicFeedAdapter during its component scan. A simple solution is
to move it to a sibling package. If MonsterFeedApplication is in
com.acme.foo, then put the adapter config class in com.acme.bar. That
way, boot won't consider it "part" of the application
This was indeed the problem. After implementing Gary's suggestion, everything works perfect.
See the answer to this question and its follow up for a similar question about inbound mail adapters.
In essence, each feed adapter is created in a child context that is parameterized.
In that case the child contexts are created in a main() method but there's no reason it couldn't be done in a service invoked by .handle().
I searched around on the internet a bit but thought I might get some insight by just posting on stackoverflow and seeing if there were any opinions out there.
I'm wondering if anyone has an opinion of which is preferred between these two ways of setting up a page object:
public class LoginPage extends PageObject{
public void typeEmail(String email){
driver.findElement(EMAIL_SELECTOR).sendKeys(email);
}
public void typePassword(String pw){
driver.findElement(PASSWORD_SELECTOR).sendKeys(email);
}
public void submit(){
driver.findElement(SUBMIT_SELECTOR).click();
}
}
...and...
public class LoginPage extends PageObjects{
public void login(String email, String password){
driver.findElement(EMAIL_SELECTOR).sendKeys(email);
driver.findElement(PASSWORD_SELECTOR).sendKeys(email);
driver.findElement(SUBMIT_SELECTOR).click();
}
}
Originally, I thought the second way would be better since if the login flow changes for some reason (this is unlikely with a login, but you could theorize this happening for other types of forms), you could update the login() method and this change would affect all the tests which required login.
However, if you want to verify error conditions or more things before submit(), the second solution isn't flexible enough.
Any insights would be welcome.
Page object definition : "A PageObject need not represent an entire page. It may represent a section that appears many times within a site or page, such as site navigation."
The keys points of a PageObject :
- The public methods represent the services that the page offers
- Try not to expose the internals of the page
- Generally don't make assertions
- Methods return other PageObjects
- Need not represent an entire page
- Different results for the same action are modelled as different methods
SOURCE
Your two settings aren't PageObject but there is some similarities.
Personally I prefer to use another level of abstraction like:
public void typeEmail(String email){
fillField(EMAIL_SELECTOR, email);
}
And an implementation in your SeleniumWrapper class
public void fillField(WebElement selector, String text){
driver.findElement(selector).sendKeys(text);
}
This makes code more good-looking
This is not directly related to PageObjects, but still this is a way to prettify your code if you dont use BDD, or keyword-driven approach
I am wondering if there is a best practice for creating a REST API with ASP.NET MVC 3? At the moment I am thinking of creating a controller for each version of the REST API. For example, so far I have:
public class V1Controller : Controller
{
public V1Controller()
{
}
public ActionResult GetUser(string userId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
public ActionResult GetUsersByGroup(string groupId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
}
Then for the views I overwrite the _ViewStart.cshtml to remove the layout and then I have Results.cshtml that just outputs the data that is formatted in the controller action, right now JSON. Having every single REST call in one controller seems like a bit too much but it is the best way I can think of so that I can keep clean separate versions of the API so that when it comes to creating version 2 of the API, I can create a V2Controller and not break the existing API to give people time to switch over to the new API.
Is there a better way to create a REST API with ASP.NET MVC 3?
I was able to find a decent solution using MVC's use of Areas.
First, I wanted to have my API follow this URL Definition:
http://[website]/[major_version]_[minor_version]/{controller}/{action}/...
I also wanted to break up the different versions in separate Project files and use the same Controller names in each version:
"../v1_0/Orders/ViewOrders/.." => "../v2_3/Orders/ViewOrders/.."
I searched around and found a workable solution with the use of MVC Areas.
I created a new project in my solution called "Api.Controllers.v1_0" and, as a test, put a SystemController.cs file in there:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class SystemController : Controller
{
public ActionResult Index()
{
return new ContentResult() {Content = "VERSION 1.0"};
}
}
}
I then added a v1_0AreaRegistration.cs file:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class v1_0AreaRegistration : AreaRegistration
{
public override string AreaName
{
get{ return "v1_0";}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"v1_0",
"v1_0/{controller}/{action}/{id}",
new { controller = "System", action = "Index", id = UrlParameter.Optional }
);
}
}
}
I walked through the same steps above for a "..v1_1" project with the corresponding files in there, added the projects as references into my "Api.Web" MVC project and was off and running.
If all you are returning is JSON, you do not need a view. Jusr return
new JsonResult(){Data = Data};
Look in here.
Also in terms of versioning, versions can be implemented as different controllers or as extra methods in the same controller. But without knowing why you would need versions and why your clients (which I assume are browsers) would need to know about versioning is not clear from your question.
A controller such as the one you posted in your example code should always keep that methods that you have now for instance GetUsersByGroup() with the same signature. I don't see how there could be a different version of that method.
The inputs are group and repository (which I believe comes from DI). The output is a list of users in JSON format. That's all that matters to the users of the API. What you do inside this method is no one's business.
You should think more of inputs and outputs. You shouldn't be changing the signatures of existing actions unless it is really neccessary to do so.
Think of the controller class in terms of implementing the interface. You have an interface and controller class is it's implementation (I mean you don't need to have it but just think of it in that way). You will rarely change the interface once one or several classes implement it. But you might add the methods to it. And that requires only changes in implementing classes - it does not break the functionality of the API and everyone who's using it will be able to continue using it.
I'm a first-time user of the AOP features of Unity 2.0 and would like some advice. My goal is to be able to log method calls in an ASPX page, like so:
public partial class Page2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[Log]
private void Testing()
{
}
}
Here is the code for the LogAttribute:
public class LogAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler(Order);
}
}
Now the LogHandler:
public class LogHandler : ICallHandler
{
public LogHandler(int order)
{
Order = order;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
string className = input.MethodBase.DeclaringType.Name;
string methodName = input.MethodBase.Name;
string preMethodMessage = string.Format("{0}.{1}", className, methodName);
System.Diagnostics.Debug.WriteLine(preMethodMessage);
return getNext()(input, getNext);
}
public int Order { get; set; }
}
The problem I have is how to use the [Log] attribute. I've seen plenty of example of how to configure the interception settings, for example:
container.AddNewExtension<Interception>();
container.Configure<Interception>().SetDefaultInterceptorFor<ILogger>(new InterfaceInterceptor());
But this implies that I have an interface to intercept, which I don't. I have the ASPX page which uses the [Log] attribute.
so how can I configure Unity to make use of the [Log] attribute? I've done this before using PostSharp and would like to be able to use Unity to do the same.
Cheers.
Jas.
You're unfortunately not going to get this to work in an ASP.NET page with Unity interception.
Unity interception uses a runtime interception model. Depending on the interceptor you choose, you'll either get a subclass with virtual method overrides to call the call handlers (VirtualMethodInterceptor) or a separate proxy object (Interface or TransparentProxyInterceptor) which execute the call handlers and then forward to the real object.
Here's the issue - ASP.NET controls creation and calls to your page, and there's no easy way to hook into them. Without controlling the creation of the page object, you can't use the VirtualMethodInterceptor, because that requires that you instantiate a subclass. And you can't use the proxy version either, because you need ASP.NET to make calls through the proxy.
PostSharp gets around this because it's actually rewriting your IL at compile time.
Assuming you could hook into the creation of the page object, you'd have to use the VirtualMethodInterceptor here. It's a private method, so you want logging on "self" calls (calls from one method of the object into another method on the same object). The proxy-based interceptors can't see those, since the proxy is a separate instance.
I expect there is a hook somewhere to customize how ASP.NET creates object - BuildManager maybe? But I don't know enough about the details, and I expect it'll require some pretty serious hacking to get work.
So, how do you get around this? My recommendation (actually, I'd recommend this anyway) is to use the Model-View-Presenter pattern for your ASP.NET pages. Make the page object itself dumb. All it does is forward calls to a separate object, the Presenter. The Presenter is where your real logic is, and is independent of the details of ASP.NET. You get a huge gain in testability, and you can intercept calls on the presenter without all the difficulty that ASP.NET gives you.
Where is the most fitting place for security and roles authorization to fit into the model view presenter design pattern?
Would it be for all pages that implement security to implement a specific interface, say IAuthorizedView that's along the lines of
public interface IAuthorizedView : IView
{
IUser user;
void AuthorizationInitialized();
void AuthorizationInvoked();
}
Then handled inside the presenter level
public abstract class Presenter<TView> where TView : IView
{
public TView View { get; set; }
public virtual void OnViewInitialized()
{
}
public virtual void OnViewLoaded()
{
}
}
public abstract class AuthorizationSecuredPresenter<TView>
: Presenter<TView> where TView : IAuthorizedView
{
public override void OnViewInitialized()
{
View.AuthorizationInitialized();
base.OnViewInitialized();
}
public override void OnViewLoaded()
{
View.AuthorizationInvoked();
base.OnViewLoaded();
}
}
This would be my first idea on it, the only question this would leave me is if we move from solely web based and added any type of API that required authorization on the service level that there would end up alot of duplication of access checking or is that perfectly acceptable to verify twice and should be designed for up front?
Here is something that you might want to consider.
I would use the decorator pattern to authorize each call to your object separatly.
Let's say you have the following class:
public class MyService
{
public virtual void DoSomething()
{
//do something on the server
}
}
You would then proceed to create a base decorator to implement the default constructor like this:
public class MyServiceDecoratorBase : MyService
{
public MyServiceDecoratorBase(MyService service)
{
}
}
Once this is setup, you can actually start to decorate by creating an authorization decorator like this:
public class MyServiceAuthorizationDecorator : MyServiceDecoratorBase
{
private readonly MyService _service;
public MyServiceDecoratorBase(MyService service)
{
_service = service;
}
public override void DoSomething()
{
//TODO: Authorize the user here.
_service.DoSomething();
}
}
So now that the main classes are done... how are you going to call all this? Easy!
MyService service = new MyServiceAuthorizationDecorator(new MyService());
service.DoSomething();
Now... the advantage of all that is that your authorization logic is completely decoupled from your main service(or object) logic. Why is this important? Testability. You can test your main service independently of your authorization logic. This correspond to the Open/Close Principle.
Now, let's say you want to calculate performance on those pesky methods... add a decorator! Logging? Another decorator! They can all be chained that way. Of course, the more you add and the heavier it gets but I think that it's worth it for the advantage it gives.
Comments?
Your design looks fine; as for your concluding question ...
if we move from solely web based and
added any type of API that required
authorization on the service level
that there would end up alot of
duplication of access checking or is
that perfectly acceptable to verify
twice and should be designed for up
front?
The answer is emphatically yes - you may even want to verify permissions more often than that, even when these checks are semi-redundant. I can think of at least three times I'd check security in a typical web application (with role-based security requirements):
First, inside your business layer - to ensure security is applied no matter what the execution context.
Second, when creating the view itself (or its presenter), it's important to make sure users only see features for which they have permission - both for security reasons and so they don't waste their time.
Third, when constructing menus to make sure that users don't see functionality that they don't have permission to use. Again, this is for both security and usability reasons. You don't want to distract users with features they can't use, if you can help it.
The View should handles just the UI. It should setup the dialog/form/controls however you need it. When the user tries to authorize hand the data off to the presenter.
The presenter then should take that data and validate it using the API and model exposed from the model.
In my CAD/CAM application the actual API reside in lowest of my application the utility assembly. I wrap and interface around it so that if I chance my security API the upper levels do not see anything different. The Utility tells me if the entered information is valid or not and what level of security to grant the person.
Any more specific depends on the exact security API you are using.