Is it possible to manipulate retrofit url without method parameter? - retrofit

Network call are made like this
#GET("/api/video/{slug}/show")
void getVideoData(#Path("slug") String slug,Callback<VideoContainerGSON>cb);
Now I need to add wariable path before "/api" e.g:
/en/api/video/{slug}/show
Or
/sp/video/{slug}/show
That parameter is global wide, so without setting alteration all network call will use same language path.
Question: Is there a way to alter it without method signature or I must change method signature to
#GET("/{lang}/api/video/{slug}/show")
void getVideoData(#Path("lang") String lang, #Path("slug") String slug,Callback<VideoContainerGSON>cb);

You can use string xmls to resolve your issue. You can put your api root in string.xml and override it in other xmls for example:
in values/string.xml
<string name="api_root">http://yourapiroot.com/en</string>
in values-es/string.xml
<string name="api_root">http://yourapiroot.com/sp</string>
and when you create your adapter set api root from resources as is shown in the code below:
new RestAdapter.Builder()
.setEndpoint(context.getString(R.string.api_root))
.build()
if you do not want to make the rest api from device language you can set params which defines language in api root in method where you build RestAdapter
And after that you start your paths from /api/... For example:
#GET("/api/video/{slug}/show")
void getVideoData(#Path("slug") String slug,Callback<VideoContainerGSON>cb);

Related

in ASP.NET core (.NET5) how can i write logs for each request on separate files? Using Serilog or other

I'm new to .NET and to webservice development, so i'm not exactly sure how to implement the requirement i have.
My webservice gets a POST request with some data, which i need to
process to generate a pdf file: name_YYYYMMDDHHmmss.pdf.
For monitoring this i want to have a separate logfile for each request, named like the output file: name_YYYYMMDDHHmmss.log
I would like to avoid passing a config object into every class/function in which i need to add stuff to the log file
I've managed to install Serilog and it works for what i need, but not when i get concurrent requests. I'm also not exactly sure how simultaneous requests are handled in .NET (i have no thread specific code written so far), but as far as i can tell, when i change Global Logger file name, that object is shared across all threads so all of them write to the same file.
I've looked at a bunch of solutions, but i haven't managed to find nothing that suits this, and it seems most people have everything into 1 file...
Is there any clue or tips you can give me? I'm open to using something other than Serilog.
One way to have dynamic file names based on a specific context is by using the Serilog.Sinks.Map and then, via a middleware in the request pipeline, you can add a property to the log context that drives the file name to be used when writing to the log.
Examples of similar usage of Serilog.Sinks.Map to decide which file name to use at run-time:
Serilog - can not log to multiple files based on property
In Serilog dynamically changing log file path?
The best solution that I found to this problem was using Serilog.Sinks.Map. I configured my Logger something like this:
Log.Logger = new LoggerConfiguration()
.WriteTo.Map("Name", "Default", (name, wt) => {
var fileName = name == "Default" ? "log" : $"{log-{name}}"
wt.File($"./{fileName}-.txt");
}).CreateLogger();
Then on my controller, on each method where I needed this feature, I enclosed all the instructions inside a LongContext like this:
[HttpGet]
public IHttpActionResult Get() {
using (LogContext.PushProperty("Name", "theFileName") {
// ...
_myService.Method1();
// ...
}
}
public class MyService : IMyService {
// ...
public void Method1() {
// ...
Log.Information("This is what happened at this point…");
// ...
}
// ...
}
So all the Log's inside will use that context and it will write on a different file with the name you set for that context without having to modify any Log.Information/Error/Warning/etc that you already have on your code.
This is the ugly part... you have to define a context on a root place in order to make those Logs write on a different file. So for a controller method, the first thing you have to do is to enclose all with a LogContext.

How to send non-string objects into pipeline with ExecuteApplicationPipeline preparer

I am trying to create a dbmigrate file which will call a ExecuteApplicationPipeline preparer, but one of the mandatory parameters is a ChannelRepository as on screenshot, is there any way to fullfil that parameter through dbmigrate file?
I have also tried leaving out that parameter but it doesn't work.
Looking at the source code of ExecuteApplicationPipeline or ExecutePipeline reveals that all parameters need to be of type String. After all you're configuring it via properties file
protected Domain site;
protected Application application;
protected String pipelineName;
protected String startNodeName;
protected Hashtable<String, String> pipelineParameters = new Hashtable<>();
You can create a pipeline of your own that translates a domain name (e.g. YOUR_ORG-YOUR_CHANNEL) into a repository and executes the call against ProcessApplication-Create. See for example

Specify run time parameter dependency in Unity

I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}

How to set the location for a SOAP service in Flex?

I have successfully generated my web service proxies using the FlexBuilder menus. This particular web service has an internal (or incorrect) "location" specified in its WSDL. This means that when I go to make an actual method call, it fails because the DNS name specified in the location field is wrong. (It shows as "aborted" in fire bug).
How do I set the location attribute on the service object? I have done this in Java and php before but cannot figure out how to do it in Flex.
update:
The field that needs to be changed is listed below. It is called "WSDL-endpoint." So the question is: How do I do this programmatically given the generated web service object (the one that extends WebServiceWrapper)?
<annotation name="ServiceConfig">
<item name="DEFAULT_ENTITY_PACKAGE">valueObjects</item>
<item name="WSDL-endpoint">http://eoc7/eoc7/api.asmx</item>
<item name="LINKED_FILE"></item>
</annotation>
Flash Builder stores webservice address in .fml file in .model subdirectory of your flex project. You can edit this file, then reopen the project. But the easiest way is to remove yor Data/Service and rebuild it using wizard.
Here is the way to programmatically set the "location" of a web service in a Flex SOAP service:
Go to the generated service class and set this property on the _service control object:
_serviceControl.endpointURI = "http://uri-to-real-location"
So I created a simple method to set this from outside the class:
public function setEndpointUri(uri : String) : void
{
_serviceControl.endpointURI = uri;
}
This is the only way I could get it to work, in the generated stub for your service:
import com.adobe.fiber.core.model_internal;
Also:
/**
* Override super.init() to provide any initialization customization if needed.
*/
protected override function preInitializeService():void
{
_needWSDLLoad = false; // to prevent loading the default WSDL
super.preInitializeService();
// Initialization customization goes here
wsdl = "http://localhost/yourservice?wsdl";
_needWSDLLoad = true;
model_internal::loadWSDLIfNecessary();

pass parameters to HTTPService and use them inside the URL

Flex3 + Cairngorm. I have my service in Servicis.mxml:
<mx:HTTPService id="docIndex" url="{URL_PREFIX}/jobs/{???}/docs" resultFormat="e4x"/>
And I call it from my generic restful delegate like this:
public function index(params:Object):void {
var call:AsyncToken = services.getHTTPService(resourceName+"Index").send(params);
call.addResponder(responder);
}
I want to know how I can use the params Object I pass inside the url definition (the ??? above). And please tell me how you would go about searching an answer to this in the documentation, I'd like to be a little more independet on these problems...
EDIT: I'll explain myself if you didn't understand my problem:
I have a restful api written in rails to which I'm connecting. Doc is a child resource of Job. If I want to get all docs I have to supply a job_id too. Therefore in the service the url must be changed for each .send() call, with the proper job_id (the ??? part above). I'd like to call it like myDelegate.index({job_id:34}) and insert that job_id field in the Service URL.
Write a class that extends HTTPService and allows you to set parameters into the url. Then, in your index function you can fetch it with services.getHTTPService, and call a function you create that sets the url values for you.
In your service locator create an instance of your class rather than a flat HTTPService.

Resources