ServiceStack AutoQuery, Implicit/Explicit Queries - servicestack

I have the following Request DTO:
[Route("/processresults")]
public class FindProcessResults : QueryBase<ProcessResult, ProcessResultDto> {}
ProcessResult has a property named Id (Int32). I have two ProcessResults in my database, Id 1 and 2.
When I perform a GET to /processresults?Id=1 I get a single ProcessResult returned. Great.
However when I POST this JSON I get two ProcessResults returned. The query is not executing. When I add the property Id to FindProcessResults the JSON call does work, however I have not set EnableUntypedQueries to false.
PostData: {"Id":"1"}
What could be the issue here?
Bonus points, if I make a POST with Form Data I get the following exception:
{
ResponseStatus: {
ErrorCode: "RequestBindingException",
Message: "Unable to bind request",
StackTrace: " at ServiceStack.Host.RestHandler.CreateRequest(IRequest httpReq, IRestPath restPath)\ \ at ServiceStack.Host.RestHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName)"
}
}
However if I do the same (a post) with x-www-form-urlencoded the query works as intended (returns a single result).
Conclusion: Whilst I can resolve this issue by adding the parameter I wish to query by (Id) to the typed request, this defeats the purpose of what I am trying to achieve, a generic query mechanism for my data store. The functionality already exists for the GET version of the request.
I believe it is to do with the implementation of AutoQueryServiceBase:
public virtual object Exec<From>(IQuery<From> dto)
{
SqlExpression<From> q;
using (Profiler.Current.Step("AutoQuery.CreateQuery"))
{
q = AutoQuery.CreateQuery(dto, Request.GetRequestParams());
}
using (Profiler.Current.Step("AutoQuery.Execute"))
{
return AutoQuery.Execute(dto, q);
}
}
This is using Request.GetRequestParams() which will return parameters from the Query String or the Form Parameters, whilst a JSON request is attempting to be deserialized into <From> dto. The From type FindProcessResults has no Id property and so it is not populated and passed to the Query.
Requested HTTP Request/Response:
Request
POST /processresults HTTP/1.1
Host: localocl
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 36d4b37e-0407-a9b3-f2f2-5b024d7faf7f
{"Id":1}
Response
Cache-Control → private
Content-Length → 1580
Content-Type → application/json; charset=utf-8
Date → Mon, 03 Nov 2014 21:20:43 GMT
Server → Microsoft-IIS/8.5
Vary → Accept
X-AspNet-Version → 4.0.30319
X-Powered-By → ServiceStack/4.033 Win32NT/.NET, ASP.NET
{"Offset":0,"Total":2,"Results"....

You should strongly consider using GET requests for consuming AutoQuery services which is more appropriate HTTP Verb to use, that's also more cacheable and introspectable.
If you want to POST and you don't want to use a HTML Form POST (i.e. x-www-form-urlencoded Content-Type) you will need to formalize the parameters by adding them to the Request DTO:
[Route("/processresults")]
public class FindProcessResults : QueryBase<ProcessResult, ProcessResultDto>
{
public int Id { get; set; }
}
Otherwise it will try to deserialize the JSON into an empty DTO where any non-existing properties are ignored.

Related

How to add unauthorized WWW-Authenticate field to response header using Micronaut Security?

Using Micronaut Security, I would like the application to respond to a unauthorized request with a WWW-Authenticate header field for basic authentication, like this:
WWW-Authenticate: Basic realm="User Visible Realm"
Is it possible to do this inside the configuration file (ie. application.yaml)?
If not, how would you recommend doing this with minimum boilerplate?
My current security configuration:
security:
intercept-url-map:
- pattern: /**/*
access:
- isAuthenticated()
redirect:
forbidden:
enabled: false
unauthorized:
enabled: false
Thanks!
I don't know that this is possible via configuration.
One way to achieve this is a server filter. The code below is groovy.
#Filter("/**")
class AuthenticateHeaderFilter extends OncePerRequestHttpServerFilter {
#Override
protected Publisher<MutableHttpResponse<?>> doFilterOnce(HttpRequest<?> request, ServerFilterChain chain) {
return Publishers.map(chain.proceed(request)) { response ->
if (response.status() == HttpStatus.UNAUTHORIZED) {
response.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"my realm\"")
}
return response
}
}
#Override
int getOrder() {
return Integer.MIN_VALUE
}
}

How to assign file-name to Azure DocumentDB attachment?

I am uploading an image to documentDb. I assign filename to slug property. I retrieve the attachement using media link obtained during upload.
My expectation is that when I retrieve attachment I would get my filename back. But in contrary Azure returned slug as null. I have double checked content of the retrieved attachement is correct.
Two questions:
Am I misusing slug property?
Where should I assign custom properties?
Here is my Code:
public async Task<string> UploadAttachment(string selfLinkId, Stream mediaStream, string contentType, string fileName)
{
Document foundDocument = (await _client.ReadDocumentAsync(selfLinkId)).Resource;
ResourceResponse<Attachment> resp = await _client.CreateAttachmentAsync(foundDocument.AttachmentsLink, mediaStream, new MediaOptions { ContentType = contentType, Slug = fileName, });
string mediaLink = resp.Resource.MediaLink;
return mediaLink;
}
public async Task<MediaResponse> GetAttachment(string mediaLink)
{
//Use DocumentClient to read the Media content
MediaResponse content = await _client.ReadMediaAsync(mediaLink);
return content;
}
Are you sure the content type is being set correctly?
As per this documentation, slug and contentype are needed only when uploading raw media, which is your scenario. Also, have you checked the Documents Explorer in the azure portal to see how the document and its attachments are stored? Are the values shown there the ones you are expecting?
As per the same documentation, this is an example of how a POST of raw media should look like:
POST https://contosomarketing.documents.azure.com/dbs/hUwBcw==/colls/hUwBc+gfDX4=/docs/hUwBc+gfDX4DAAAAAAAAAA==/attachments HTTP/1.1
x-ms-date: Thu, 14 Aug 2014 22:40:25 GMT
authorization: type%3dmaster%26ver%3d1.0%26sig%3dza46lCo9nNr0%2fGMjryG8S%2b26ZsFABUYPlW3ebq26nDg%3d
x-ms-version: 2014-08-21
Content-Type: image/png
Slug: brush.png
Content-Length: 244

Providing Response Model sample JSON data on the metadata page in ServiceStack

Anyone know a way that you can provide some sample data to show on the metadata page in ServiceStack for your response models?
For this response model
public class GetIncidentResponse
{
public IEnumerable<Incident> Incidents { get; set; }
}
I'm getting this on the metadata page
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: length
{}
When I'd like to be able to display something like
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: length
{ "Filter example 1", "Filter example 2"}
#mythz comment fixed my problem. Changing the IEnemerable interfaces to IList worked.

Recommended pattern for REST service which requires HTTP headers?

I am implementing a RESTful service which will be consumed by a Dojo framewwork's RestStore, which will permit binding the service to various widgets like an interactive grid or a type-ahead ajax select.
The RestStore wants to send and receive the HTTP Range and Content-Range headers in order to restrict the results of the queries to particular subrange.
What is the best practice pattern in ServiceStack (new API) for reacting to HTTP headers as part of the service? Normally, the service method like Get doesn't have access to the HTTP headers, unless I have missed an alternate API.
The current way that I see is to implement an attribute like
public class RangeSupporter : Attribute, IHasRequestFilter, IHasResponseFilter
which will parse the headers on request, and write the headers on response. The DTO would then be marked for this filter.
The filter would transfer the values, say 'First' and 'Last' in and out of the DTO. However, to know that the DTO even has such attributes, it would have to have some marker interface like
interface IHasRangeSupport {
int First { set; get; }
int Last { set; get; }
int Total { set; get; }
}
so that the filter can transfer the information into and out of the DTO the with code similar to:
var r = request as IHasRangeSupport;
if (r != null) {
/// Access the DTO attributes for the range parameters
}
This seems like a lot of ceremony, and a very awkward implementation.
Is there a better pattern for accessing the HTTP headers when implementing a REST service?
In my particular use case, supporting non-REST endpoints (like SOAP) are not required. Only the HTTP end-point is important.
What is the best practice pattern in ServiceStack (new API) for reacting to HTTP headers as part of the service?
I believe you can get the headers in your service class...
public class FooService : Service
{
public object Get(Foo reqeust)
{
//get header
var h1 = base.RequestContext.GetHeader("headerName");
//get header differently
var h2 = base.Request.Headers.Get("headerName");
}
}

servicestack Razor view with request and response DTO

I'm having a go with the razor functionality in service stack.
I have a razor cshtml view working for one of my response DTO's.
I need to access some values from the request DTO in the razor view that have been filled in from some fields from the REST route, so i can construct a url to put into the response html page and also label some form labels.
Is there anyway of doing this? I don't want to duplicate the property from the request DTO into the response DTO just for this html view. Because i'm trying to emulate an existing REST service of another product, i do not want to emit extra data just for the html view.
eg
http://localhost/rest/{Name}/details/{Id}
eg
#inherits ViewPage<DetailsResponse>
#{
ViewBag.Title = "todo title";
Layout = "HtmlReport";
}
this needs to come from the request dto NOT #Model
link to user
link to user details
If you want to access the Request DTO it needs to be referenced by either by adding the Request to the Response DTO (which you don't want to do), so the other option is to add it to the IHttpRequest.Items Dictionary which is the preferred way to pass data between your filters and services.
public class MyService : Service {
public object Any(MyRequest request) {
base.Request.Items["RequestDto"] = request;
return MyResponse { ... };
}
}
Then in your view:
#{
var myRequest = (MyRequest)base.Request.Items["RequestDto"];
}
Wrapping Re-usable functionality in Request Filters
If you find you need to access the Request DTO in your views a lot, then rather than manually assigning it in each service, you can create a Request Filter Attribute or if you want it assigned all the time in a Global Request Filter.
public class SetRequestDtoAttribute : RequestFilterAttribute {
public override void Execute(
IHttpRequest req, IHttpResponse res, object requestDto)
{
req.Items["RequestDto"] = requestDto;
}
}
Then you can add this behavior by decorating the [SetRequestDto] attribute on different levels of granularity on either an Action, Service, Request DTO or base class.

Resources