Global request/response interceptor - servicestack

What would be the easiest way to setup a request/response interceptor in ServiceStack that would execute for a particular service?
A request filter (IHasRequestFilter) works fine but a response filter (IHasResponseFilter) is not triggered if the service returns non 2xx status code. I need to retrieve the status code returned by the method as well as the response DTO (if any).
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application and I couldn't find a way clean way to isolate per functionality the tasks that need to be executed in those methods.
Is there some extension point in ServiceStack that I am missing that would allow me to execute some code before each service method and after each service method? A plugin would be ideal but how can I subscribe to some fictitious BeforeExecute and AfterExecute methods that would allow me to run some custom code?
UPDATE:
Just after posting the question I found out that global response filters are executed no matter what status code is returned by the service which is exactly what I needed. So one last question: Is it possible to retrieve the service type that will handle the request in a request filter? I need to check whether this service is decorated by some custom marker attribute.

I have found out a solution to my question about how to retrieve the service type in a custom request/response filter:
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var metadata = EndpointHost.Metadata;
Type serviceType = metadata.GetServiceTypeByRequest(requestDto.GetType());
...
}

A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application
Quick note, you can opt-in and choose only what requests should use a custom service runner, e.g:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return useCustomRunner(actionContext.RequestType)
? new MyServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}

IHttpRequest has OperationName. I think thats what you are after.

Related

Spring Integration - Service Activator - Method Signature

I have a general question. We are upgrading some old code to v4.1.3 of spring-integration. Let's say we have a service activator that receives a domain object of type Foo, and returns the same object on the output channel (after changing some properties of that object).
Our existing code has signatures like below. Is it the right convention? If I don't need the headers, can I return my payload directly and will the framework wrap it into a Message?:
public Message<Foo> computeValue(Foo payload, #Headers Map<String, Object> headerMap) {
//...
return MessageBuilder.withPayload(payload).copyHeaders(headerMap).build();
}
Yes, you don't need do that. More over that is pointless because in case of Service Activator the Framework populates request headers to the reply message independently of your effort.
So, consider do not care about headers at all if you don't need to do some specific logic on the matter.

Test are passing and they shouldn't

Before I added [Authorize] filters for each controller, I created test cases and made them pass. Now I have added said filter on each controller's method but they still pass, but I think they shouldn't since there is no logged user. Am I not seeing something?
PS: I haven't mocked Identity 2.0
Edit:
Basically I'm mocking a repository, through the unit of work pattern. In my unit test, I get a reference to the List the mock repository uses, in order to test.
[TestMethod]
public async Task CanCreateCustomerAndRedirectToDetails() {
// Arrange
Customer customer = NewCustomer(); // Gets a new customer that is NOT on the list
CustomerCreateViewModel viewModel = Mapper.Map<CustomerCreateViewModel>(customer); // Maps to viewmodel
// Act
RedirectToRouteResult result = (RedirectToRouteResult) await Controller.Create(viewModel); // Sends to controller
// Assert
// Up to this point, Customers is the mock repository's list. so it should contain the new created customer since the controller should call the insert method
// Normally, the assertion should pass. But after I implemented [Authorize] filter, I would expect the controller not to do anything (besides redirecting to login) and this test would fail
Assert.IsNotNull(Customers.FirstOrDefault(e => e.ID == customer.ID));
Assert.AreEqual("Details", result.RouteValues["action"].ToString());
}
There's nothing in your unit test which responds to or in any way examines the Authorize attribute. Or any attribute.
Attributes don't actually change the behavior of the method. They decorate the method in a way that other code (such as in a framework, like ASP.NET MVC) might recognize. The Authorize attribute is used by the ASP.NET MVC framework. But the attribute alone doesn't change the method.
MSTest doesn't use the Authorize attribute. So if you want to test its presence on the method, you'd need to examine it in some way. Though that shouldn't really be necessary. The functionality of the framework is already very thoroughly tested by its vendor.
All your test needs to be testing is the functionality of the method, which it is. You don't need to test the functionality of the ASP.NET Framework.
You can test attributes very effectively by unit testing the classes which define those attributes. So if you, for example, created a custom attribute (let's call it CustomAuthorize) then you would have a class defining that attribute (CustomAuthorizeAttribute) and you could unit test that class, separately from unit testing your controllers.

Unit testing claims based authorization with ThinkTecture ClaimsAuthorizeAttribute

We are controlling access to our application's resources and actions by using ThinkTecture's MVC ClaimsAuthorizeAttribute and would like to be able to include some unit test coverage using Moq.
Ideally, I'd like to write a test which requests a controller action decorated with:
[ClaimsAuthorize("operation_x", "resource_1")]
... so as to enter our AuthorizationManager's CheckAccess override method during execution of the test.
Our CheckAccess override simply gets the action and resource from the incoming AuthorizationContext ("operation_x" and "resource_1") and determines whether the Principal has the resource/action combination as a claim and returns true if a match is found.
The test would pass or fail based on the result of our CheckAccess override.
Most of the examples I've found online are about unit testing custom Authorize attributes or testing whether a controller action has been decorated by an AuthzAttribute. There don't seem to be many examples of testing ThinkTecture's ClaimsAuthorize attribute.
Is it even possible to achieve what I've described? If so, please advise!
Thanks
You may be looking to do more work than necessary - you don't need to test ThinkTecture's ClaimsAuthorizeAttribute, because ThinkTecture have already done that. You should write tests which test your own code - namely the outcome of the actions performed inside your override of CheckAccess.
If you want to check whether the ThinkTecture attribute works as it should, you should look into setting up an integration test which causes the controller action in question to be invoked.

adding custom methods in Hook environment?

i am adding a new method into CalEventLocalServiceImpl using hook...
my code is ..
public class MyCalendarLocalServiceImpl extends CalEventLocalServiceWrapper {
public MyCalendarLocalServiceImpl(CalEventLocalService calEventLocalService) {
super(calEventLocalService);
// TODO Auto-generated constructor stub
}
public List getUserData(long userId) throws SystemException{
DynamicQuery query=DynamicQueryFactoryUtil.forClass(CalEvent.class)
.add(PropertyFactoryUtil.forName("userId").eq(userId));
List deatils=CalEventLocalServiceUtil.dynamicQuery(query);
return deatils;
}
}
liferay-hook.xml:
<service>
<service-type>
com.liferay.portlet.calendar.service.CalEventLocalService
</service-type>
<service-impl>
com.liferay.portlet.calendar.service.impl.MyCalendarLocalServiceImpl
</service-impl>
</service>
my question is how to use getUserData from jsp file.
Can anybody help me out....
i think u didn't gt my question...i want list of events based on USERID from Calendar ...to achieve this task what i need to do??
I assume getUserData() is not overridden but a new method (can't look up currently). This is not what you can do when overriding a service. Instead you'd have to add a new Service and make it available to the portal.
Remember that a customized ("hooked") jsp is running in the portal classloader, while your overloaded service is running in the hook's classloader. Thus, if you create a new service and make the service.jar available to Liferay (e.g. on the global classpath) you can call it from JSPs. The interface of Liferay services can not be extended through an overloaded service.
In case getUserData() is already in the interface (as I said I can't look up currently), you just need to call the CalendarLocalServiceUtil from your jsp and it will be delegated to your wrapper.
Just to add to Olaf's answer and comments...
if you you want to extend CalEventLocalService service with just "getUsetData" and use it in one jsp than building your own service might be overkill. Simply put your code from "getUserData" in jsp. Otherwise follow Olaf's suggestions.

Extending log4net - Adding additional data to each log

We're working on logging in our applications, using log4net. We'd like to capture certain information automatically with every call. The code calling log.Info or log.Warn should call them normally, without specify this information.
I'm looking for a way to create something we can plug into log4net. Something between the ILog applications use to log and the appenders, so that we can put this information into the log message somehow. Either into ThreadContext, or the LogEventInfo.
The information we're looking to capture is asp.net related; the request url, user agent, etc. There's also some information from the apps .config file we want to include (an application id).
I want to get between the normal ILog.Info and appender so that this information is also automatically included for 3rd party libraries which also use log4net (Nhibernate, NServiceBus, etc).
Any suggestions on where the extensibility I want would be?
Thanks
What you are looking for is called log event context. This tutorial explains how it works:
http://www.beefycode.com/post/Log4Net-Tutorial-pt-6-Log-Event-Context.aspx
In particular the chapter 'Calculated Context Values' will interesting for you.
Update:
My idea was to use the global context. It is easy to see how this works for something like application ID (in fact there you do not even need a calculated context object). Dynamic information like request url could be done like this:
public class RequestUrlContext
{
public override string ToString()
{
string url;
// retrieve url from request
return url;
}
}
The object is global but the method is called on the thread that handles the request and thus you get the correct information. I also recommend that you create one class per "information entity" so that you have a lot of flexibility with the output in the log destination.

Resources