How to add different headers for different build flavors using Retrofit - retrofit

Im new to retrofit and this question might be trivial. Here is a simple api interface
public interface ApiRetrofitService {
#GET("territories/url")
#Headers({"Token: XXXXX"})
public Call<List<Territory>> getTerritories();
#GET("territories/url/current")
#Headers({"Token: XXXXX"})
public Call<Territory> getCurrentTerritory();
}
I want to load the Headers from a static resource file, to keep it simple lets say I want to have the headers values stored in strings.xml in a <string name="token">XXXXX</string>. Is there a way that i can add values from the strings.xml in the ApiRetrofitService header. I'm hopping for something like this:
public interface ApiRetrofitService {
#GET("territories/url")
#Headers({"Token:" + R.strings.token})
public Call<List<Territory>> getTerritories();
#GET("territories/url/current")
#Headers({"Token:" + R.strings.token})
public Call<Territory> getCurrentTerritory();
}
And in general how do i solve the issue where i need to add different headers for differend build flavors? Thanks

It's too late but it may help others.
You can use the dynamic header like
#GET("territories/url/current")
public Call<Territory> getCurrentTerritory(#Header("Token") String token);
and when you call get method
if (BuildConfig.DEBUG) {
//call getCurrentTerritory(//debug string token)
}else{
//call getCurrentTerritory(//production string token)
}

Related

how to do Shell Navigation with complex objects in .net MAUI or Xamarin Forms?

Recently I've started using shell and I noticed an improvement in page transitioning and a bug I was facing using NavigationPage was fixed just by replacing it with shell.
So I was excited to use it.
However soon after I realized I can't send objects from page to page through shell like I could using a constructer of a page. I searched a bit and now know that shell passes strings only. I turned the object into JSON but then faced an exception due to long URI length.
Honestly, I am disappointed. I thought something this important would be implemented in shell... but In any case, how do you guys work around this?
For Maui.
See (Xamarin) Process navigation data using a single method.
Also mentioned in maui issue. Adapting the Maui invocation there:
await Shell.Current.GoToAsync("//myAwesomeUri",
new Dictionary { {"data", new MyData(...)} });
This uses IQueryAttributable and ApplyQueryAttributes to pass an IDictionary<string, object> query.
(The Xamarin example shows IDictionary<string, string>, but its , object in Maui, so you can pass any object values.)
Thus the string parameters you pass can be used to look up corresponding objects.
From that (Xamarin) doc (modified to show looking up an object):
public class MonkeyDetailViewModel : IQueryAttributable, ...
{
public MyData Data { get; private set; }
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
Data = (MyData)query["data"];
}
...
}
For Xamarin Forms, the limitation to string values makes this a bit ugly. One approach is to have a static that holds possible objects, which you look up using a string. This is tolerable when the objects are all pre-defined, but is a bit clumsy if you are manually altering those objects.
public class MonkeyDetailViewModel : IQueryAttributable, ...
{
public static Dictionary<string, MyData> KeyedData;
// "static": One-time class constructor.
public static MonkeyDetailViewModel()
{
KeyedData = new Dictionary<string, MyData>();
KeyedData["data1"] = new MyData(...);
// ... other versions of the data ...
}
public MyData Data { get; private set; }
public void ApplyQueryAttributes(IDictionary<string, string> query)
{
string whichData = query["data"]; // In example, gets "data1".
Data = KeyedData[whichData];
}
...
}
Usage:
await Shell.Current.GoToAsync("//myAwesomeUri",
new Dictionary { {"data", "data1"} });
Xamarin NOTE: The static dictionary makes it possible to maintain multiple instances of MyData. The "hack" alternative is to have MyData Data be static, and explicitly set it before GoToAsync - but this is risky if you ever might have a MonkeyDetailView on nav stack, go to a second one, then go back to first one - you'll have overwritten the Data seen by the first view.

How to bind multiple file uploads with model in web api?

I can't see what's missing here.
I have a model that looks like this:
public class ModelDto
{
public string X { get; set; }
// ...
public IList<IFormFile> Attachments { get; set; }
}
It is used for a POST endpoint in Web Api, like this:
[HttpPost()]
public async Task<ActionResult<ResponseModel>> PostEndpoint([FromForm] ModelDto modelDto)
{
// ...
}
When I POST with Postman, with Form-Data, and fields, including Attachment[0] as a file, I receive a model, complete with all other fields, but without any file. But I do receive the file in the request. If I look at this.Request.Form.Files, it's there, but it was not loaded as part of the model.
So, obviously, I can manually re-attach the list of files to the appropriate part of the model. But why doesn't the binding work?
Thanks
Well, I finally got it, so the problem was on the Postman side of how I wrote the request.
For arrays of text keys, the [] notation is used. It must not be used for arrays of files.
So instead of sending Attachments[0] or Attachments[], I just had to send Attachments as the key to each file. Then the binding works fine.

Configurable Topic name with Rebus

Topic needs to configrable via config file.
Below is the code. I wonder if this is the best solution or any built-in support, or better solution?
public class TopicNameConvention : ITopicNameConvention
{
private readonly Config _config;
public TopicNameConvention(Config config)
{
_config= config;
}
public string GetTopic(Type eventType)
{
switch (eventType.Name)
{
case nameof(Order):
return _config.Topic.Name;
//... more
}
throw new Exception("Topic name not exist");
}
}
If you intention is to manually be able to configure the topic name for each of your event types, then please go for it.
My own personal opinions is that this seems pretty rigid, and I would fear that you would have to update too many things at the same time, whenever you introduce a new event type.
Why not just go with
public string GetTopic(Type eventType) => eventType.Name;
which can handle all .NET types in the world (just be sure that you do not have two event types with the same name in two different namespaces).

HttpServletRequest - Get Literal Path

I have a method marked with Spring's #RequestMapping that includes an HttpServletRequest method parameter.
If I print out the results of a call to "request.getServletPath()" when the path is, say, "/things/{thingId}", I will get "/things/2489sdfjk43298f," where the {thingId} path parameter has been replaced with the actual value.
I want to print out the literal request path "/things/{thingId}"; I.e. with the curly-braced, un-replaced path parameter "{thingId}."
Is this possible in any way?
Edit: After looking at Sotirios's second comment below, I realize I may be looking at the problem backward. Here's what I'm actually trying to do...
I am trying to making a single endpoint under "/**" that gets the path from the HttpServletRequest, which I use to look up a value in an enum. This enum has several fields, one of which is obviously the aforementioned path, but another is the path of a target JSP file. I then put this path into a ModelAndView object and return it to display the page.
This was going just fine until I hit the first endpoint with a path parameter, because I obviously can't place the value "/things/2489sdfjk43298f" into the enum, because that will only match for that one specific thing with that one specific ID.
So perhaps the actual question would be: How would I do that look-up when parts of the path will change due to path parameters? Is there some sort of wildcard-containing String format I can use?
I guess this is turning into more of a enum-lookup/String-matching question. My bad.
Edit 2: Shortened example of the enum thing I'm talking about:
public enum JspEndpointType {
HOME("/home", "jsp/home");
private static final Map<String, String> pathMap;
private String requestPath;
private String jspPath;
static {
pathMap = new HashMap<>();
for (JspEndpointType jspEndpointType : JspEndpointType.values()) {
pathMap.put(jspEndpointType.getRequestPath(), jspEndpointType.getJspPath());
}
}
private JspEndpointValue(String requestPath, String jspPath) {
this.requestPath = requestPath;
this.jspPath = jspPath;
}
public String getRequestPath() {
return requestPath;
}
public String getJspPath() {
return jspPath;
}
public static String getByRequestPath(String requestPath) {
return pathMap.get(requestPath);
}
}
Shortened example of my endpoint:
#RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView showPage(HttpServletRequest request) {
return new ModelAndView(JspEndpointType.getByRequestPath(request.getServletPath()));
}
So things essentially boil down to trying to add to the enum a value like this:
THINGS("/things/{thingId}", "jsp/things/whatever")
..and then being able to pass in the path "/things/2489sdfjk43298f" and get back "/jsp/things/whatever."
Edit 3: I found this StackoverFlow question which directed me to Spring's UriComponentsBuilder, specifically the "fromPath" method. However, that seems to be the reverse of what I'm trying to do...
You may look for the #RequestMapping annotation on your own, using reflection.

How to allow client pass my object through webservice?

Sorry if this is stupid question, because I'm a bit confused about .NET remoting and distributed object.
I want to write a webservice, and in one of its methods, I want user to pass one my object's instance as parameter. It will greatly reduces number of parameters, and help user call this method more effectively. I create some class, but when distributing them to client, only class name remains, all properties and methods are gone, just like this
public class CameraPackages
{
private readonly List<CameraPackage> _packages;
public CameraPackages()
{
_packages = new List<CameraPackage>();
}
public void AddNewCamera(CameraPackage package)
{
_packages.Add(package);
}
public void RemoveCamera(CameraPackage package)
{
if(_packages.Contains(package))
_packages.Remove(package);
else
throw new ArgumentException();
}
}
into this: (in Reference.cs)
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
public partial class CameraPackages {
}
How can I do to allow user use my object?
Thank you so much.
Web Services will only serialise public properties, so you can't do that (in that way) using web services.
You will need to manage your list of objects client side, then send the data in a transfer object (a class with just properties).
Have a look at this.

Resources