How to get the parameters and pass to the Model - xamarin.ios

Good afternoon. I`m using mvvmCross 5.2.0 and Xamarin.
I am trying to pass three parameters through a link and when opening my App, treat them in a Model, however I am not able to find how, by AppDelegate, I call a Model passing the parameters.
Link:
valdemar://?token=1234&name=Rafael
AppDelegate:
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
...
//How to get the parameters and pass to the Model?
}

Related

Omitting fields during serialization for specific Gson serializer

I have a stateless REST API build on Spring Boot 1.4.2. I want to log all the API calls into elk. Requests and responses data (headers, parameters, payload) need to be logged as well. I don't want to log them 1:1 - I want to filter out sensitive data etc.
I made an aspect that is intercepting my #RestController's methods invocation. I created custom annotation for method's parameter that should be logged (I use it on payloads annotated as well by #RequestBody) following this article and it gave me access to my data transfer objects in my #Around advice. I dont care about their type - I would like to call logger.debug(logObject) and send this log to logstash.
As far as I understand log message should be send as JSON with JSONLayout set in Log4j2 appender to ease things on the logstash side. So I serialize my logObject into JSON log message but during this and this only serialization I want to filter sensitive data out. I can not use transient because my controller depends on the same field.
Can I somehow create an #IgnoreForLogging annotation, that will be detected only by my custom Gson serializer that I use within logging advice and will be ignored within standard Spring's infrastructure? Is my logging into logstash approach even correct (I am trying to set it up for the first time)?
I can't believe I missed that in documentation. Here is the link
My custom annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface IgnoreForLogging {
}
Strategy for serializing objects:
public class LoggingExclusionStrategy implements ExclusionStrategy {
#Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getAnnotation(IgnoreForLogging.class) != null;
}
#Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
}
Serializing log message in aspect class:
Gson gson = new GsonBuilder()
.setExclusionStrategies(new LoggingExclusionStrategy())
.create();
String json = gson.toJson(logObject);
This way Spring internally uses default serializer that doesn't know about #IgnoreForLogging and I can take advantage of my annotation in other places.

constructor parameters on controller actions

I am trying to create a custom manager which is passed in the controller when it is being called and I am having troubles understanding the current implementation of new MVC5 project in c#.
Here is the default implementation:
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
{
UserManager = userManager;
SignInManager = signInManager;
}
above all of that are declarations for them:
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
Now from my understanding the SignInManager and UserManager get created when application gets created for the first time in Startup.Auth.cs which looks like this:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
So now whenever I call UserManager I will get that first instance that was created when project ran for the first time.
I have 2 questions. Question 1 is is anything I said above wrong and Do I have a wrong understanding of how MVC5 works?
Question2: How is UserManager and SignInManager generated and passed in the controller? Where is the code that creates that first instance of the manager and passes it in the controller? I am assuming it is app.CreatePerOwnContext that does it. If so, can I then just create my own Manager and then register it with Owin in the same fashion and reuse throughout the project? Will my code get the latest data from the database if I do this and not cache it?
The code you're showing is coming from the IMO very ugly MVC5 template, which works out of the box but does some ugly things.
This constructor:
public AccountController(ApplicationUserManager userManager,
ApplicationSignInManager signInManager)
makes you think OWIN automagically injects the managers for you. But in fact this is not the case. That is why the template comes with the ugly properties you supplied in the questions. When you do not change anything to the template, the default constructor is called (also present in the template). To try it, just delete, or comment, the default constructor and you'll see the AccountController can't be created anymore.
So what is actually happening there is that both managers are located using the Service Locator anti pattern in the getters of the supplied properties.
So now whenever I call UserManager I will get that first instance that was created when project ran for the first time?
No this is not the case. What this line:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
does, is creating a delegate to the Create method of both managers. The managers are cached within an Owin Request. The next request the delegates are called again and you get a fresh ApplicationUserManager etc.
To be a little bit more verbose this line could be rewritten as:
Func<ApplicationUserManager> userManagerFactory = () => ApplicationUserMangager.Create();
app.CreatePerOwinContext<ApplicationUserManager>(userManagerFactory);
So if you would a breakpoint here:
public ApplicationUserManager UserManager
{
get
{
// place breakpoint here
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
// ....
You would see that while stepping through the code, you will hit the line where you created the UserManagerFactory which in his turn will call the Create() method of the ApplicationUserManager.
How is UserManager and SignInManager generated and passed in the controller
It isn't! You would need to use dependency injection for that.
If so, can I then just create my own Manager and then register it with Owin in the same fashion and reuse throughout the project
Yes you can. You can completely refactor the ApplicationUserManager you also got 'for free' in the template. As long as you supply a factory method to the 'CreatePerOwinContext' extension method.
Will my code get the latest data from the database if I do this and not cache it?
The instances are cached on per request base. So each request you will get a new one, with a new DbContext etc.
I'm unsure how familiar you are with dependency injection but MVC5 is a pretty easy framework to start with it, IMO.
I once wrote a blogpost how to configure my DI container of choice (Simple Injector) to use with the MVC5 template.
I also wrote several answers here on SO regarding this template: specifically this one, should interest you. This one is interesting also!

WebAPI get not converting properly to model binding object

I"m using WebAPI with MVC4, doing a http get that looks like this:
api_version=2&products=[{"id":97497,"name":"iPad"}]&pageno=1
The signature of the get action controller that maps to this call is:
[HttpGet]
public string Get([FromUri] ProductRequest request){ ... }
The problem is that the ProductRequest object passed into the Get action method above contains nulls for products, while all other values are Ok.
So it seems that it has trouble converting products=[{"id":97497,"name":"iPad"}] into the right object type, which is defined as:
public IEnumerable<Products> products { get; set;} in ProductRequest model and Products class looks like:
public int id { get; set; }
public string name { get; set; }
As, an additional information, when using the same call with a POST instead of a GET, it works fine, the object is converted properly.
So, what am I doing wrong, how can I get http GET to properly convert the query parameters to the model passed in?
I think you confused between HTTP POST and HTTP GET that's why you did get the product as null. You could have a look at What's the difference between GET and POST
Basically, I think you could use TempData but it has pros and cons and depend on the context how you use it.
You can do it through the url, but you don't use JSON. Here's what your URL should look like:
api_version=2&products[0].id=97497&products[0].name=iPad&pageno=1
If you wanted to add more products in the same request, you would increment the array index:
{urlasabove}&products[1].id=4234&products[1].name=iPadmini
This is fine for your request, but can quickly get out of hand. For a complex object in a GET request you may consider using a POST instead. Or, you could include the parameters in the GET body but that's not necessarily the best idea. See discussion on this SO question.

Checking for an attribute on a destination property inside a custom AutoMapper TypeConverter

I have a custom type converter that converts UTC DateTime properties to a company's local time (talked about here: Globally apply value resolver with AutoMapper).
I'd now like to only have this converter do its thing if the property on the view model is tagged with a custom DisplayInLocalTime attribute.
Inside the type converter, if I implement the raw ITypeConvert<TSource, TDestination> interface, I can check if the destination view model property being converted has the attribute:
public class LocalizedDateTimeConverter : ITypeConverter<DateTime, DateTime>
{
public DateTime Convert(ResolutionContext context)
{
var shouldConvert = context.Parent.DestinationType
.GetProperty(context.MemberName)
.GetCustomAttributes(false)[0].GetType() == typeof(DisplayInLocalTimeAttribute);
if (shouldConvert) {
// rest of the conversion logic...
}
}
}
So this code works just fine (obviously there's more error checking and variables in there for readability).
My questions:
Is this the correct way to go about this? I haven't found anything Googling around or spelunking through the AutoMapper code base.
How would I unit test this? I can set the parent destination type on the ResolutionContext being passed in with a bit of funkiness, but can't set the member name as all implementors of IMemberAccessor are internal to AutoMapper. This, and the fact that it's super ugly to setup, makes me this isn't really supported or I'm going about it all wrong.
I'm using the latest TeamCity build of AutoMapper, BTW.
Don't unit test this, use an integration test. Just write a mapping test that actually calls AutoMapper, verifying that whatever use case this type converter is there to support works from the outside.
As a general rule, unit tests on extension points of someone else's API don't have as much value to me. Instead, I try to go through the front door and make sure that I've configured the extension point correctly as well.

Monotouch - global variables

How can I store/access global variables within a monotouch application? I am retrieving the GPS Location (using Monotouch.CoreLocation.CLLocationManager) during the FinishedLaunching method of the AppDelegate. How do I then access that information from a property on that appdelegate (from a view, for example)? Or is there another preferred method for global data?
UPDATE:
I just want to grab the location once, at startup, then have access to that location from all my views. Here's my AppDelegate - I'd like to access the locationManager field from a view. I can certainly add a property to do so, but I guess my question is "How do I access that property from a view (or can I even, considering it's a delegate)"?
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
private CLLocationManager locationManager = new CLLocationManager();
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
locationManager.Delegate = new GpsLocationManagerDelegate();
locationManager.StartUpdatingLocation();
window.AddSubview (navController.View);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
Generally, most people will tell you to avoid global variables and instead pass what you need into the delegate. (I would agree with that sentiment).
However, you can use a singleton class, a service locator, or a static class with static fields/properties to get global variable-like behavior in C# (or any other Dotnet/Mono compatible language).
In your case, I presume you wrote the class GpsLocationManagerDelegate yourself. If so, you can change the constructor to take parameters for the necessary information (the view, a reference to the app delegate, and/or a reference to the location manager) and store it in your GpsLocationManagerDelegate instance. If you didn't write GpsLocationManagerDelegate yourself and it's not declared sealed, subclass it and create an appropriate constructor.
This example seems close to what you're after: http://www.conceptdevelopment.net/iPhone/MapKit01/Main.cs.htm
You should make locationManager a public property, then you can access it from most places in the app like so:
CLLocationManager LocationManager {get;set;}
AppDelegate delegateReference =
(AppDelegate)UIApplication.SharedApplication.Delegate;
then access the locationmanager anywhere in code via:
delegateReference.LocationManager
Generally, you should setup such things as singletons, setup within the AppDelegate.

Resources