Adding Authorization Header in Web View

So, this is my second post about web view. Still from my last project, I had to deal with some problems regarding web view. One of them was adding authorization header in web view. When I look up on net, there were so many answers, but most of them didn’t work for me. So, I thought I should share which method that works for me.

Android Web View Renderer

In Android, I simply put the Authorization header on web view renderer. In some forums, there’re some different opinions about where we should put this header, like put it in web chrome client, but those methods didn’t work in my case. So, this is how I added the authorization header in my project.

public class HybridWebViewRenderer : WebViewRenderer
{
    public HybridWebViewRenderer(Context context) : base(context)
    { }
    public HybridWebViewRenderer(){ }

    protected override void OnElementChanged(ElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        var webView = Control as Android.Webkit.WebView;
        var Token = Settings.AccessToken;

        Dictionary headers = new Dictionary()
        {
            {"Authorization", "Bearer " + Token }
        };
        this.Control.LoadUrl(Control.Url, headers);
    }

}

I put it on OnElementChanged method, as a result, whenever the user navigate to other page in web view, causing the url changed, this method will be fired. So, the header will be added whenever user make new request in web view.

iOS Web View Delegate

Different from it’s Android counter part, we can’t add the Authorization header on web view renderer in iOS, we have to put it on web view delegate. In iOS web view delegate, there’s a method called ShouldStartLoad

Just like its name, this method is fired whenever the web view load new page. So, it’s actually pretty similar with the Android, but the way this method works is little bit different. In Nutshell, what we gonna do in this method are :

  1. Checking if the request has Authorization Header
  2.  If not, Copy the request and then add the header to the copied request.
  3. Cancel the original request without Authorization Header
  4. If the request already has the header, just let it through

So, this how it looks like in real code.

public class HybridWebViewRenderer : WebViewRenderer
{
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        Delegate = new HybridUiWebViewDelegate(this);

        this.ScrollView.DecelerationRate = UIScrollView.DecelerationRateNormal;
        var webView = e.NewElement as HybridWebView;
    }

}

public class HybridUiWebViewDelegate : UIWebViewDelegate
{
    public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
    {
        if (!request.Headers.ContainsKey(new NSString("Authorization")))
        {
            var copy = request.MutableCopy() as NSMutableUrlRequest;
            var token = Settings.AccessToken;

            NSMutableDictionary dic = new NSMutableDictionary();
            dic.Add(new NSString("Authorization"), new NSString("Bearer " + token));
            copy.Headers = dic;

           string currentUrl = request.Url.ToString();

           if (currentUrl.ToLower() != StaticVariables.CurrentUrl.ToLower())
           {
               StaticVariables.CurrentUrl = currentUrl;
               StaticVariables.NavigationStack.Add(currentUrl);
           }

           webView.LoadRequest(copy);

           return false;
      }
      return true;
    }
}

Hope this method also works for you.

Nested Checkbox in Xamarin Forms

We already have two posts discussing about check box, but I wanna to take it one step further. So, in this post we’ll discuss one of the most common behavior that a check box has. Let’s say we have a list of check boxes, and every one of them, the check box, also have list of check boxes of their own, or in short, a list of nested check boxes. In this nested check box, when we check the parent box, all the children boxes will be automatically checked as well. On the contrary, when on of child is unchecked, the parent will be automatically unchecked as well. So, we’ll be discussing how that process can be executed in Xamarin forms, started from the custom content view of the check box.

Parent and Child Check Box

Just like the previous post about check box, I created custom content view of check box. Because we gonna have two different check box, so I created two different content view, one for parent, one for the child. And to distinguish between those two check boxes, I put the box in the left for parent, and in the right for the child. Here’s how the parent check box content view looks like



	
        
            
                
                
            

            
            
        
	

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ChildrenCheckBox : ContentView, INotifyPropertyChanged
{
    public ChildrenCheckBox()
    {
        InitializeComponent();
    }

    public static BindableProperty IconSourceProperty =
        BindableProperty.Create(nameof(IconSource), typeof(string), typeof(ChildrenCheckBox), null, BindingMode.TwoWay);

    public string IconSource
    {
        get => (string)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }

    public static BindableProperty MenuTitleProperty =
         BindableProperty.Create(nameof(MenuTitle), typeof(string), typeof(ChildrenCheckBox), null, BindingMode.TwoWay);

    public string MenuTitle
    {
        get => (string)GetValue(MenuTitleProperty);
        set => SetValue(MenuTitleProperty, value);
    }
}

And the following code is the Children Check box code.


	
        
            
                
                
            

            
            

        
	

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ParentCheckBox : ContentView, INotifyPropertyChanged
{
    public ParentCheckBox()
    {
        InitializeComponent();
    }

    public static BindableProperty IconSourceProperty =
        BindableProperty.Create(nameof(IconSource), typeof(string), typeof(ParentCheckBox), null, BindingMode.TwoWay);

    public string IconSource
    {
        get => (string)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }

    public static BindableProperty MenuTitleProperty =
        BindableProperty.Create(nameof(MenuTitle), typeof(string), typeof(ParentCheckBox), null, BindingMode.TwoWay);

    public string MenuTitle
    {
        get => (string)GetValue(MenuTitleProperty);
        set => SetValue(MenuTitleProperty, value);
    }
}

Parent and Children View Model

After done with the UI, now we’re talking about the business process, about the view model. Just like the content view, we also have two kind view model, one for the parent, and one for the children. Let’s started with the parent. In the parent view model, beside all standard methods, we gonna have two main method. First, SetParent. So, we’ll receive list of children check boxes as parameter and then in this method we’ll set the parent of this check boxes to the current parent view model. The second method is UpdateChildren, is where we set the all children checked when the parent is also checked.

public class ParentCheckboxViewModel : BaseViewModel
{
    protected bool isChecked;
    public bool IsChecked
    {
        get => isChecked;
        set
        {
            SetProperty(ref isChecked, value);
            UpdateChildren();
            UpdateImageSource();
        }
    }

    protected string menuTitle;
    public String MenuTitle
    {
        get => menuTitle;
        set => SetProperty(ref menuTitle, value);
    }

    protected string iconSource;
    public string IconSource
    {
        get => iconSource;
        set => SetProperty(ref iconSource, value);
    }

    protected ObservableCollection children;
    public ObservableCollection Children
    {
        get => children;
        set => SetProperty(ref children, value);
    }

    protected ChildrenCheckboxViewModel selectedChild;
    public ChildrenCheckboxViewModel SelectedChild
    {
        get => selectedChild;
        set => SetProperty(ref selectedChild, value);
    }

    public ICommand ChildTappedCommand { get; set; }

    public ParentCheckboxViewModel(ObservableCollection _children)
    {
        this.Children = _children;
        ChildTappedCommand = new Command(ChildTapped);
        IsChecked = false;
        SetParent();
    }

    private void ChildTapped()
    {
        foreach(ChildrenCheckboxViewModel child in Children)
        {
            if (child.MenuTitle == SelectedChild.MenuTitle)
                child.IsChecked = !child.IsChecked;
        }
    }

    protected void SetParent()
    {
        foreach(ChildrenCheckboxViewModel child in Children)
        {
            child.Parent = this;
            child.IsChecked = false;
        }
    }

    protected void UpdateChildren()
    {
        if(IsChecked)
        {
            foreach(ChildrenCheckboxViewModel child in Children)
            {
                child.IsChecked = true;
            }
        }
    }

    protected void UpdateImageSource()
    {
        if (IsChecked)
        {
            IconSource = "CheckBox.png";
        }
        else
        {
            IconSource = "CheckBoxEmpty.png";
        }
    }
}

In Children view model, beside all the basic methods, we have one important method, UpdateParent. In this method, we’ll uncheck the parent if the current children is getting unchecked by user.

public class ChildrenCheckboxViewModel : BaseViewModel
{
    protected bool isChecked;
    public bool IsChecked
    {
        get => isChecked;
        set
        {
            SetProperty(ref isChecked, value);
            UpdateImageSource();
            UpdateParent();
        }
    }

    protected string menuTitle;
    public String MenuTitle
    {
        get => menuTitle;
        set => SetProperty(ref menuTitle, value);
    }

    protected string iconSource;
    public string IconSource
    {
        get => iconSource;
        set => SetProperty(ref iconSource, value);
    }

    protected ParentCheckboxViewModel parent;
    public ParentCheckboxViewModel Parent
    {
        get => parent;
        set => SetProperty(ref parent, value);
    }

    protected void UpdateImageSource()
    {
        if (IsChecked)
        {
            IconSource = "CheckBox.png";
        }
        else
        {
            IconSource = "CheckBoxEmpty.png";
        }
    }

    protected void UpdateParent()
    {
        if (!IsChecked)
        {
            Parent.IsChecked = false;
        }
    }
}

Let’s try it out

Now that we’ve finished all preparation, let’s put all of them in a real case. So, I’ve created a simple program that utilize the parent and children check box. Here’s the code.



	
       
                         
                               
                                
                                    
                                        
                                        
                                    
                                     
                                     
                                                       
                                                            
                                                                    
                                                            
                                                        
                                     
                                
                               
                          
       
	


public class NestedCheckboxViewModel: BaseViewModel
{
    protected ObservableCollection listChildren1;
    public ObservableCollection ListChildren1
    {
        get => listChildren1;
        set => SetProperty(ref listChildren1, value);
    }

    protected ObservableCollection listChildren2;
    public ObservableCollection ListChildren2
    {
        get => listChildren2;
        set => SetProperty(ref listChildren2, value);
    }

    protected ObservableCollection listChildren3;
    public ObservableCollection ListChildren3
    {
        get => listChildren3;
        set => SetProperty(ref listChildren3, value);
    }

    protected ObservableCollection listChildren4;
    public ObservableCollection ListChildren4
    {
        get => listChildren4;
        set => SetProperty(ref listChildren4, value);
    }

    protected ObservableCollection listChildren5;
    public ObservableCollection ListChildren5
    {
        get => listChildren5;
        set => SetProperty(ref listChildren5, value);
    }

    protected ObservableCollection listParent;
    public ObservableCollection ListParent
    {
        get => listParent;
        set => SetProperty(ref listParent, value);
    }

    protected ParentCheckboxViewModel selectedParent;
    public ParentCheckboxViewModel SelectedParent
    {
        get => selectedParent;
        set => SetProperty(ref selectedParent, value);
    }

    public ICommand ParentTappedCommand { get; set; }

    public NestedCheckboxViewModel()
    {
        ListChildren1 = new ObservableCollection()
        {
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 1.1" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 1.2" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 1.3" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 1.4" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 1.5" },
        };

        ListChildren2 = new ObservableCollection()
        {
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 2.1" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 2.2" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 2.3" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 2.4" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 2.5" },
        };

        ListChildren3 = new ObservableCollection()
        {
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 3.1" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 3.2" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 3.3" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 3.4" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 3.5" },
        };

        ListChildren4 = new ObservableCollection()
        {
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 4.1" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 4.2" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 4.3" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 4.4" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 4.5" },
        };

        ListChildren5 = new ObservableCollection()
        {
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 5.1", },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 5.2" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 5.3" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 5.4" },
            new ChildrenCheckboxViewModel(){ MenuTitle = "Child CheckBox 5.5" },
        };

        ListParent = new ObservableCollection()
        {
            new ParentCheckboxViewModel(ListChildren1){ MenuTitle = "Parent Checkbox 1" },
            new ParentCheckboxViewModel(ListChildren2){ MenuTitle = "Parent Checkbox 2" },
            new ParentCheckboxViewModel(ListChildren3){ MenuTitle = "Parent Checkbox 3" },
            new ParentCheckboxViewModel(ListChildren4){ MenuTitle = "Parent Checkbox 4" },
            new ParentCheckboxViewModel(ListChildren5){ MenuTitle = "Parent Checkbox 5" },
        };

        ParentTappedCommand = new Command(ParentTapped);
    }

    private void ParentTapped()
    {
        foreach(ParentCheckboxViewModel parent in ListParent)
        {
            if (parent.MenuTitle == SelectedParent.MenuTitle)
                parent.IsChecked = !parent.IsChecked;
        }
    }
}

If you run the code, you’ll have a list of nested check boxes. And then if you check one of the parent, all the children boxes will be checked, and if you uncheck one of the children, the parent will be automatically uncheck.

Credit:

  • Check Box Icon from FlatIcon, Checked Check Box icon by Google, Empty Check Box icon by Dave Gandy
  • Flow List View by Daniel Luberda (github)