Servicestack Razor Markdown View Resolution - servicestack

I want to display a view after facebook authentication in my application but I'm getting the json response instead the html view, according to the documentation the view resolution is the following:
The resolution order ServiceStack's uses to resolve the appropriate Markdown template to use for rendering HTML output is:
If the Web Service specifies a template (via a customized IHttpResult.TemplateName response) - then a View with that name.
A view with the same name as the Response DTO, looking first in /Views then in /Views/Shared
A view with the same name as the Request DTO, looking first in /Views then in /Views/Shared
these are my DTOs
public class FacebookRequest{}
public class FacebookResponse{}
this is my route configuration
Routes.Add<FacebookRequest>("/User/facebook");
my view has the folloing code:
#inherits ViewPage<MyProject.Services.Dto.FacebookResponse>
this is a facebook response
Service method:
[ClientCanSwapTemplates]
public FacebookResponse Get(FacebookRequest userRequest)
{
return new FacebookResponse();
}
As far as I understand if I have a view located in the "views" directory with the same responseDTO it should wire the view with the response from the service.

Adding comment as answer
SS uses the exact name of the response DTO class and looks for a view file with that exact name on the filesystem, unless you provide a DefaultView attribute. So, if your view (in your example) wasn't Views/FacebookResponse.cshtml exactly, it won't work. Using the inherits viewpage statement doesn't help SS resolve the view. It's looking for the exact file name in a specific location. I'm not 100% on this - but I seem to recall that it was a case sensitive match too.

Related

How to use Custom Routes with Auto Query

Using the first example in the ServiceStack Auto Query documentation in a project structured similar to the EmailContacts sample project (i.e. separate projects for the ServiceModel and ServiceInterface), how would one register the custom route "/movies" defined by the Route attribute?
[Route("/movies")]
public class FindMovies : QueryBase<Movie>
{
public string[] Ratings { get; set; }
}
Normally, custom routes such as these can be register by passing the ServiceInterface assembly when instantiating AppHostBase:
public AppHost() : base("Email Contact Services", typeof(ContactsServices).Assembly) {}
However, the FindMovies request DTO does not have an associated service and therefore won't be included. No routes are registered.
If I pass typeof(FindMovies).Assembly instead of or in addition to typeof(ContactsServices).Assembly, then the pre-defined route will be registered (i.e. shows up in the metadata, postman, etc.) but the custom route is still not registered (i.e. does not show up in the metadata, postman, etc.).
What is the best way to register the custom route using attributes when there is no service and the ServiceModel and ServiceInterface are in separate projects?
These issues should be resolved in v4.0.24+ that's now available on MyGet.
There's a new AutoQueryFeature.LoadFromAssemblies property to specify an additional list of assemblies to scan for IQuery Request DTO's. This automatically looks in the assemblies where your other Request DTO's are defined so in most cases nothing needs to be done as it will automatically be able to find your query services.
The routes for Query DTO's should now appear on the metadata pages as well as Swagger and Postman metadata API's.

servicestack Razor view pages for response dto's with same name but different namespace

i have 2 dto's in different sub namespaces but the same class name for response dto, in the same assembly.
with the razor view pages in servicestack, it looks for the response dto .cshtml in the View folder.
is it possible to have 2 separate razor view pages for different namespaces?
eg
namespace mydto.Cars
{
public class queryResponse
{
}
}
namespace mydto.Bikes
{
public class queryResponse
{
}
}
Nope, it scans for view pages by name only. I would add the namespace tail to the DTO that describes how the DTO is different, e.g. CarsQueryResponse.
With ServiceStack in general you don't want to have multiple DTOs with the same name but different namespaces, e.g. Every Request DTO must be unique by name, this is what allows you to call a web service knowing the name only.

ServiceStack Request DTO with variable number of properties

I'd like to create an endpoint that is the front end for a query service and I'd like to support a scenario where any number of arguments can be passed into the service via querystring parameters.
This is the sort of URL I want:
/queries/MyQuery?argument1=value&arg2=value
The DTO object structure itself is fairly straightforward (a property such as Dictionary<string, object>) but I'm stuck on what the route should look like. Is this possible via the RouteAttribute or do I need to go another direction?
Here's a good answer that explains Routing in ServiceStack.
Only the PathInfo is apart of the Route, the Request DTOs on all routes/services are also automatically populated based on the Request Params on the QueryString/FormData etc.
So if you know what the QueryString is going to be you can just add it as properties on the Request DTO and they will get automatically populated.
If you don't know what they are, but you still want access to the QueryString you can get it from the base.Request property in your Service, e.g:
class MyServices : Service
{
public object Get(MyQuery request)
{
foreach (var entry in base.Request.QueryString) {
...
}
}
}

Where would I get the base URI In my ServiceStack markdown page?

I am looking to serve an image from my root path test.com/some.png but this markdown page may be displayed on [Post]test.com/Item or [Put]test.com/Item/123 So I am looking for a way to get the base URI to form the image link.
You can use the literal text ~/ inside a Markdown page gets converted to a virtual path.
This literal is registered on start-up from the global EndpointHostConfig.MarkdownReplaceTokens property which is assigned the appHost.Config.WebHostUrl property:
this.MarkdownReplaceTokens["~/"] = appHost.Config.WebHostUrl.WithTrailingSlash();
Since it's difficult for an ASP.NET framework to determine the url its hosted at (i.e. without a request) you need to specify the preferred url you wan to use in your config. Here's an example from the servicestack.net/docs/ - ServiceStack's markdown Docs project:
SetConfig(new EndpointHostConfig {
WebHostUrl = baseUrl, //replaces ~/ with Url
MarkdownBaseType = typeof(CustomMarkdownPage),
});
Otherwise inside your service you can use base.Request or base.RequestContext.Get<IHttpRequest>() to get information about the incoming Request as well as (HttpRequest)base.Request.OriginalRequest to get the underlying ASP.NET Request object.

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