is there a good or proper way to render the output in Play Framework depending on a parameter? Example:
For HTML:
http://localhost:9000/user/get/5?v=HTML // should render HTML template
For JSON:
http://localhost:9000/user/get/5?v=JSON // should render JSON template
I think that a request interceptor could have the ability to achieve this, but I have no clue how to start or where to start :-(
Or perhaps, write a general render method that reads the parameters and output as requested, but this seems to me like overkill?
If /user/5?v=html and /user/5?v=json return two representations of the same resource, they should be the same URL, e.g. /user/5, according to the REST principles.
On client side, you can use the Accept header in your requests to indicate which representation you want the server to send you.
On server side, you can write the following with Play 2.1 to test the value of the Accept header:
public static Result user(Long id) {
User user = User.find.byId(id);
if (user == null) {
return notFound();
}
if (request().accepts("text/html")) {
return ok(views.html.user(user));
} else if (request().accepts("application/json")) {
return ok(Json.toJson(user));
} else {
return badRequest();
}
}
Note that the test against "text/html" should always be written prior to any other content type because browsers set the Accept header of their requests to */* which matches all types.
If you don’t want to write the if (request().accepts(…)) in each action you can factor it out, e.g. like the following:
public static Result user(Long id) {
User user = User.find.byId(id);
return representation(user, views.html.user.ref);
}
public static Result users() {
List<User> users = User.find.all();
return representation(users, views.html.users.ref);
}
private <T> Result representation(T resource, Template1<T, Html> html) {
if (resource == null) {
return notFound();
}
if (request().accepts("text/html")) {
return ok(html.apply(resource));
} else if (request().accepts("application/json")) {
return ok(Json.toJson(resource));
} else {
return badRequest();
}
}
Write 2 methods, use 2 routes (as you don't specify I will use Java samples:
public static Result userAsHtml(Long id) {
return ok(someView.render(User.find.byId(id)));
}
public static Result userAsJson(Long id) {
return play.libs.Json.toJson(User.find.byId(id));
}
routes:
/GET /user/get/:id/html controllers.YourController.userAsHtml(id:Long)
/GET /user/get/:id/json controllers.YourController.userAsJson(id:Long)
next you can just make a link in other view to display user's data
Show details
Get JSON
or something else...
edit #1
you can also use common if or case to determine final output
public static Result userAsV() {
String vType = form().bindFromRequest().get("v");
if (vTtype.equals("HTML")){
return ok(someView.render(User.find.byId(id)));
}
return play.libs.Json.toJson(User.find.byId(id));
}
I wanted the user to be able to be viewed in the browser as html or as json so the accepts method did not work for me.
I solved it by putting a generic renderMethod in a base class with the following style syntax
public static Result requestType( )
{
if( request().uri().indexOf("json") != -1)
{
return ok(Json.toJson(request()));
}
else
{
return ok("Got HTML request " + request() );
}
}
Related
I have a lengthy method that contains bunch of validation codes that will return Mono.error() when we found invalid objects.
#Override
public Mono<Item> update(Request item) {
return itemRepository.findById(item.getId())
.switchIfEmpty(Mono.error(new ResponseStatusException())
.flatMap (item -> {
// bunch of validation ifs
if (..) {
return Mono.error(..);
}
return itemRepository.update(item);
});
}
How do I generify and extract these validation codes returning Mono.error?
I've tried the following but it is giving warning that i need to specify Mono<Item> instead of just Mono. I want to create a common method that will return for different types of Mono
private Mono validate() {
// bunch of validation ifs
if (..) {
return Mono.error(..);
}
}
You can try with
private <R> Mono<R> validate(R itemToValidate) {
if(...){
return Mono.error(...);
}
}
The content is Encrypt with an CUSTOM encrypter. fiddler captured content body is base64 encode string in plain text
The application traffic flow:
request:
base64Encode(customEncryptFromStringTobytes(jsonString) ) -> application -> http server
response:
customDecryptFrombytesToString(base64Decode(jsonString) ) <- application <- http server
I have the encrypt/decrypt class in c#:
string EncryptToBase64(string plainText);
string DecryptFromBase64(string plainText);
I build an exe to do the transform, I wonder how To make fiddler decode request/respose body by this exe on the fly
I want Fiddler show decrypt content in inspector , and encrypt again everytime I [Reissue and Edit(E)] the request.
I found something close but Dont know how to call an exe to do decode.
http://docs.telerik.com/fiddler/KnowledgeBase/FiddlerScript/ModifyRequestOrResponse
update:
I have implement the custom inspector for Fiddler. see the answer below.
I create an Extension for custom Inspector
full example https://github.com/chouex/FiddlerExtensionExample
you will build a dll and copy the file to Inspectors and Scripts folder in fiddler. restart fiddler will load the extenion.
note:
I used pre/post-build script to copy dll and restart fiddler in vs project.
custom inspector:
This Example just beautify the json body.
public class ResponseInspector : Inspector2, IResponseInspector2
{
TextBox myControl;
private byte[] m_entityBody;
private bool m_bDirty;
private bool m_bReadOnly;
public bool bReadOnly
{
get { return m_bReadOnly; }
set
{
m_bReadOnly = value;
// TODO: You probably also want to turn your visible control CONFIG.colorDisabledEdit (false) or WHITE (true) here depending on the value being passed in.
}
}
public void Clear()
{
m_entityBody = null;
m_bDirty = false;
myControl.Text = "";
}
public ResponseInspector()
{
// TODO: Add constructor logic here
}
public HTTPResponseHeaders headers
{
get { return null; // Return null if your control doesn't allow header editing.
}
set { }
}
public byte[] body
{
get { return m_entityBody; }
set
{
// Here's where the action is. It's time to update the visible display of the text
m_entityBody = value;
if (null != m_entityBody)
{
var text = System.Text.Encoding.UTF8.GetString(m_entityBody);
if (!String.IsNullOrEmpty(text) && text.StartsWith("{"))
{
text = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(text), Formatting.Indented);
}
myControl.Text = text;
// TODO: Use correct encoding based on content header.
}
else
{
myControl.Text = "";
}
m_bDirty = false;
// Note: Be sure to have an OnTextChanged handler for the textbox which sets m_bDirty to true!
}
}
public bool bDirty
{
get { return m_bDirty; }
}
public override int GetOrder()
{
return 0;
}
public override void AddToTab(System.Windows.Forms.TabPage o)
{
myControl = new TextBox(); // Essentially the TextView class is simply a usercontrol containing a textbox.
myControl.Height = o.Height;
myControl.Multiline = true;
myControl.ScrollBars = ScrollBars.Vertical;
o.Text = "TextViewExample";
o.Controls.Add(myControl);
o.Controls[0].Dock = DockStyle.Fill;
}
}
for Traffic Tamper(not mention in question but I think this is useful):
implement AutoTamperResponseBefore() in IAutoTamper2
This Example just replace any text from "xt" to "c1" in every request body
Add a dummy header
Fiddler-Encoding: base64
and encode your body using base64 if it contains any binary data. Fiddler will decode the data before transmitting it to the server.
Taken from http://www.fiddlerbook.com/fiddler/help/composer.asp
Now I know properties do not support async/await for good reasons. But sometimes you need to kick off some additional background processing from a property setter - a good example is data binding in a MVVM scenario.
In my case, I have a property that is bound to the SelectedItem of a ListView. Of course I immediately set the new value to the backing field and the main work of the property is done. But the change of the selected item in the UI needs also to trigger a REST service call to get some new data based on the now selected item.
So I need to call an async method. I can't await it, obviously, but I also do not want to fire and forget the call as I could miss exceptions during the async processing.
Now my take is the following:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed != value)
{
this.selectedFeed = value;
RaisePropertyChanged();
Task task = GetFeedArticles(value.Id);
task.ContinueWith(t =>
{
if (t.Status != TaskStatus.RanToCompletion)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
}
});
}
}
}
Ok so besides the fact I could move out the handling from the setter to a synchronous method, is this the correct way to handle such a scenario? Is there a better, less cluttered solution I do not see?
Would be very interested to see some other takes on this problem. I'm a bit curious that I was not able to find any other discussions on this concrete topic as it seems very common to me in MVVM apps that make heavy use of databinding.
I have a NotifyTaskCompletion type in my AsyncEx library that is essentially an INotifyPropertyChanged wrapper for Task/Task<T>. AFAIK there is very little information currently available on async combined with MVVM, so let me know if you find any other approaches.
Anyway, the NotifyTaskCompletion approach works best if your tasks return their results. I.e., from your current code sample it looks like GetFeedArticles is setting data-bound properties as a side effect instead of returning the articles. If you make this return Task<T> instead, you can end up with code like this:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed == value)
return;
this.selectedFeed = value;
RaisePropertyChanged();
Articles = NotifyTaskCompletion.Create(GetFeedArticlesAsync(value.Id));
}
}
private INotifyTaskCompletion<List<Article>> articles;
public INotifyTaskCompletion<List<Article>> Articles
{
get { return this.articles; }
set
{
if (this.articles == value)
return;
this.articles = value;
RaisePropertyChanged();
}
}
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
...
}
Then your databinding can use Articles.Result to get to the resulting collection (which is null until GetFeedArticlesAsync completes). You can use NotifyTaskCompletion "out of the box" to data-bind to errors as well (e.g., Articles.ErrorMessage) and it has a few boolean convenience properties (IsSuccessfullyCompleted, IsFaulted) to handle visibility toggles.
Note that this will correctly handle operations completing out of order. Since Articles actually represents the asynchronous operation itself (instead of the results directly), it is updated immediately when a new operation is started. So you'll never see out-of-date results.
You don't have to use data binding for your error handling. You can make whatever semantics you want by modifying the GetFeedArticlesAsync; for example, to handle exceptions by passing them to your MessengerInstance:
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
try
{
...
}
catch (Exception ex)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
return null;
}
}
Similarly, there's no notion of automatic cancellation built-in, but again it's easy to add to GetFeedArticlesAsync:
private CancellationTokenSource getFeedArticlesCts;
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
if (getFeedArticlesCts != null)
getFeedArticlesCts.Cancel();
using (getFeedArticlesCts = new CancellationTokenSource())
{
...
}
}
This is an area of current development, so please do make improvements or API suggestions!
public class AsyncRunner
{
public static void Run(Task task, Action<Task> onError = null)
{
if (onError == null)
{
task.ContinueWith((task1, o) => { }, TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(onError, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Usage within the property
private NavigationMenuItem _selectedMenuItem;
public NavigationMenuItem SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = val;
AsyncRunner.Run(NavigateToMenuAsync(_selectedMenuItem));
}
}
private async Task NavigateToMenuAsync(NavigationMenuItem newNavigationMenu)
{
//call async tasks...
}
I am implementing a REST style API that allows an object to be PATCH'ed. The intention of the PATCH operation is to allow one or more properties in a class to be updated without touching an of the other properties that may be set.
The are examples of partial updates on the ServiceStack OrmLite page, but it seems to need hardcoding to indicate which fields will be partially updated. In my scenario it is upto the depend application to decide which fields to send.
I also have to cope with the scenario that the object may not have been persisted yet.
To get around this I have implemented the following:
public object Patch(Myclass request)
{
HttpStatusCode SuccessCode;
try
{
var result = (MyClass)Get(request);
if (result != null)
{
request.PopulateWithNonDefaultValues(result);
dbFactory.Run(dbCmd => dbCmd.UpdateNonDefaults(request, r => r.myId == request.myId));
}
else
{
dbFactory.Run(dbCmd => dbCmd.Save(request));
}
SuccessCode = HttpStatusCode.Accepted;
}
catch (Exception e)
{
log.Error(e);
SuccessCode = HttpStatusCode.InternalServerError;
}
return new HttpResult()
{
StatusCode = SuccessCode
};
}
It works, but something doesn't feel right, I'm sure there must be a better way?
That looks ok although you're code will be a lot shorter if you just throw let it throw C# Exceptions when there's an error and if you're inheriting from ServiceStack's New API base Service class you can use the already available Db property, e.g:
public object Patch(Myclass request)
{
var result = (MyClass)Get(request);
if (result != null)
{
request.PopulateWithNonDefaultValues(result);
Db.UpdateNonDefaults(request, r => r.myId == request.myId);
}
else
{
Db.Save(request);
}
return new HttpResult
{
StatusCode = HttpStatusCode.Accepted
};
}
The project I'm working on has the Entity Framework on top of an OData layer. The Odata layer has it's server side pagination turned to a value of 75. My reading on the subject leads me to believe that this pagination value is used across the board, rather than a per table basis. The table that I'm currently looking to extract all the data from is, of course, more than 75 rows. Using the entity framework, my code is simply thus:
public IQueryable<ProductColor> GetProductColors()
{
return db.ProductColors;
}
where db is the entity context. This is returning the first 75 records. I read something where I could append a parameter inlinecount set to allpages giving me the following code:
public IQueryable<ProductColor> GetProductColors()
{
return db.ProductColors.AddQueryOption("inlinecount","allpages");
}
However, this too returns 75 rows!
Can anyone shed light on how to truly get all the records regardless of the OData server-side pagination stuff?
important: I cannot remove the pagination or turn it off! It's extremely valuable in other scenarios where performance is a concern.
Update:
Through some more searching I've found an MSDN that describes how to do this task.
I'd love to be able to turn it into a full Generic method but, this was as close as I could get to a generic without using reflection:
public IQueryable<T> TakeAll<T>(QueryOperationResponse<T> qor)
{
var collection = new List<T>();
DataServiceQueryContinuation<T> next = null;
QueryOperationResponse<T> response = qor;
do
{
if (next != null)
{
response = db.Execute<T>(next) as QueryOperationResponse<T>;
}
foreach (var elem in response)
{
collection.Add(elem);
}
} while ((next = response.GetContinuation()) != null);
return collection.AsQueryable();
}
calling it like:
public IQueryable<ProductColor> GetProductColors()
{
QueryOperationResponse<ProductColor> response = db.ProductColors.Execute() as QueryOperationResponse<ProductColor>;
var productColors = this.TakeAll<ProductColor>(response);
return productColors.AsQueryable();
}
If unable turn off paging you'll receive 75 row by call, always. You can get all rows in following ways:
Add another IQueryable<ProductColor> AllProductColors and modify
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.SetEntitySetPageSize("ProductColors", 75); - Note only paged queries are present
config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
You should call ProductColors as many as needed, for example
var cat = new NetflixCatalog(new Uri("http://odata.netflix.com/v1/Catalog/"));
var x = from t in cat.Titles
where t.ReleaseYear == 2009
select t;
var response = (QueryOperationResponse<Title>)((DataServiceQuery<Title>)x).Execute();
while (true)
{
foreach (Title title in response)
{
Console.WriteLine(title.Name);
}
var continuation = response.GetContinuation();
if (continuation == null)
{
break;
}
response = cat.Execute(continuation);
}
I use Rx with following code
public sealed class DataSequence<TEntry> : IObservable<TEntry>
{
private readonly DataServiceContext context;
private readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly IQueryable<TEntry> query;
public DataSequence(IQueryable<TEntry> query, DataServiceContext context)
{
this.query = query;
this.context = context;
}
public IDisposable Subscribe(IObserver<TEntry> observer)
{
QueryOperationResponse<TEntry> response;
try
{
response = (QueryOperationResponse<TEntry>)((DataServiceQuery<TEntry>)query).Execute();
if (response == null)
{
return Disposable.Empty;
}
}
catch (Exception ex)
{
logger.Error(ex);
return Disposable.Empty;
}
var initialState = new State
{
CanContinue = true,
Response = response
};
IObservable<TEntry> sequence = Observable.Generate(
initialState,
state => state.CanContinue,
MoveToNextState,
GetCurrentValue,
Scheduler.ThreadPool).Merge();
return new CompositeDisposable(initialState, sequence.Subscribe(observer));
}
private static IObservable<TEntry> GetCurrentValue(State state)
{
if (state.Response == null)
{
return Observable.Empty<TEntry>();
}
return state.Response.ToObservable();
}
private State MoveToNextState(State state)
{
DataServiceQueryContinuation<TEntry> continuation = state.Response.GetContinuation();
if (continuation == null)
{
state.CanContinue = false;
return state;
}
QueryOperationResponse<TEntry> response;
try
{
response = context.Execute(continuation);
}
catch (Exception)
{
state.CanContinue = false;
return state;
}
state.Response = response;
return state;
}
private sealed class State : IDisposable
{
public bool CanContinue { get; set; }
public QueryOperationResponse<TEntry> Response { get; set; }
public void Dispose()
{
CanContinue = false;
}
}
}
so for get any data thru OData, create a sequence and Rx does the rest
var sequence = new DataSequence<Product>(context.Products, context);
sequence.OnErrorResumeNext(Observable.Empty<Product>())
.ObserveOnDispatcher().SubscribeOn(Scheduler.NewThread).Subscribe(AddProduct, logger.Error);
The page size is set by the service author and can be set per entity set (but a service may choose to apply the same page size to all entity sets). There's no way to avoid it from the client (which is by design since it's a security feature).
The inlinecount option asks the server to include the total count of the results (just the number), it doesn't disable the paging.
From the client the only way to read all the data is to issue the request which will return the first page and it may contain a next link which you request to read the next page and so on until the last response doesn't have the next link.
If you're using the WCF Data Services client library it has support for continuations (the next link) and a simple sample can be found in this blog post (for example): http://blogs.msdn.com/b/phaniraj/archive/2010/04/25/server-driven-paging-with-wcf-data-services.aspx