authentication – Is there a downside to sending a refresh token on every request to an API?

Let’s say that my user signs in and the server responds with a refresh token saved in a cookie (SameSite strict, HttpOnly, CSRF token too) and with the access token in response (saved in JS memory).

I read these guidelines in a popular Hasura article. I was wondering, though, with this method, my refresh token would be sent on every request since you can’t remove a cookie from the client-side.

Is there a downside to this? I feel like sending a token that gives infinite/long-lived access on every request is a bad practice? If so, is there a better approach so that I don’t send a refresh token on every request and only on the requests that I want to refresh my access token?

Other ways of doing this would be appreciated as well.

javascript – Tarefas assíncronas, sem refresh da página (django framework)

Tenho uma página com um botão e uma lista, quando clico no botão registra uma nova pessoa no meu banco e ela aparece na lista, após a página ser atualizada. Como faço para a lista ser atualizada sem precisar atualizar a página? (ao clicar no botão também não atualizar?)

Antes de criar uma nova pessoa:

asdasdasd

Após criar uma nova pessoa:

inserir a descrição da imagem aqui

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <div> Crie um novo modelo de pessoa aqui!</div>

    <form action="{% url 'tapp:index2' %}" method="POST">
        {% csrf_token %}

        <input type="submit" value="Criar">
    </form>

    <div>
        <h4>Lista de pessoas:</h4>
        {% for i in pessoa %}
            {{i.nome}} - {{i.ativo}} <br>
        {% endfor %}
    </div>
    {{request.POST.nome}}
    
</body>
</html>

views.py

from tapp.models import Pessoa
from django.shortcuts import redirect, render
from .models import *

app_name = 'tapp'

def index(request):
    pessoa = Pessoa.objects.all()
    return render(request, 'index.html', {'pessoa':pessoa})


def index2(request):
    pessoa = Pessoa()
    pessoa.nome = ''
    pessoa.ativo = True
    pessoa.save()

    return redirect('tapp:index')

sharepoint enterprise – Save conflict adding a content type to list after added as allowed content type in site level doc set template. What do I need to wait for or refresh?

So I’m trying to create a new content type at the site level, add it as an allowed content type in a custom document set content type, and then add it to all the libraries where the document set is used so that it’s actually there for people to use in the doc sets.

All this in a feature upgrade receiver, so C# / server-side code.

Everything goes pretty smoothly except that I’m getting “Save Conflict” SPException when I try to add the content type to each of the lists. I am used to paying attention to when I call Update() on something and then making sure to get a new reference to it if I plan to update it again to avoid those conflicts, but in this case I don’t call update on the lists, and I’m actually getting the references to the lists after I update the document set template, so I don’t see how they could have gotten stale.

Here’s basically how the code goes (although I omitted a lot of logging and error handling for clarity/brevity – I know that the error happens for each library because I’m catching those, so those exceptions are not interrupting the loop):

// at this point the new content type has been created
// successfully, so i get the _site_ level content types
SPContentType newCType = web.ContentTypes("New CType Name");
SPContentType docSetCType = web.ContentTypes("Document Set Name");

DocumentSetTemplate template = DocumentSetTemplate.GetDocumentSetTemplate(docSetCType);
template.AllowedContentTypes.Add(newCType.Id);

// update with pushdown, because the doc set is used in many document libraries
template.Update(true);

// however, that did not actually add the new content type to any libraries,
// it only updated the document set to _allow_ it.  i still need to get the
// new content type into the libraries so users can add them in the doc sets.

// so get the usages
List<SPContentTypeUsage> usages = SPContentTypeUsage.GetUsages(docSetCType).ToList();

foreach (SPContentTypeUsage usage in usages)
{
    if (usage.IsUrlToList)
    {
        // how can this not be a fresh reference to the libraries?
        // i didn't get this reference _before_ i updated the document set template,
        // i'm getting these references _after_ that update.
        SPList list = web.GetList(usage.Url);

        // i double check to make sure it wasn't automatically added when
        // the doc set template was updated, and i know it wasn't because...
        SPContentType listLevelCType = list.ContentTypes(newCType.Name);
        if (listLevelCType == null)
        {
            // ...i have a log entry here to indicate that i am about to try to add it
            listLevelCType = list.ContentTypes.Add(newCType);

            // and this is what causes the save conflict.
        }
    }
}

What am I missing here? What do I need to refresh my reference to in order to not get a save conflict when adding to the lists’ content type collections?

8 – Jquery to move field above the table – changes during page refresh

I have the below jquery code to move a multiselect field and a button above the table.

jQuery(document).ready(function($){
  $('#views-form-resources-block-1 .form-item-ka-types').insertBefore($('#views-form-myblock-block-1 table'));
  $('#views-form-resources-block-1 #edit-actions--2').insertAfter($('#views-form-myblock-block-1 .form-item-ka-types'));
});

In this code I am moving the ka-types field above myblock view. Pictorial representation as below:

enter image description here

This code works fine when I load the page at first. But when I refresh the page, the multiselect comes down and shows messed up. again when I refresh the page it works fine. not sure what the problem is. Any help on how this can be fixed?

architecture – Mobile authentication approaches, JWTs and refresh tokens

Context

I’m developing togther with my dev team a mobile app in a client-server architecture, since there will be a webclient too, allowing some users (admins) to perform certain operations from the browser.

The REST Api currently authenticates users by returning access and refresh tokens in form of JWTs. Both local (username/password) and OAuth2.0 (only Google at the moment) flows are available, as I provide the user with these two different options for authenticating.

Problem

The flows that follow are working just fine when the API is called from the webclient, but now that we’ve started developing the mobile app a big question arised: **how do we keep the user authenticated on the mobile app even after the refresh token expires?**

All the famous apps out there do not prompt the user to authenticate let’s say weekly or worst daily, but still I’m sure their authentication practices are (almost) flawless.

Tried paths

I’ve read many blog posts and articles, together with some StackExchange Q&As as reported below, but the right way to approach authentication and access persistence on mobile is still unclear.

  • Should I create a specific endpoint (or many) to provide non-expiring tokens only when the User-Agent header tells the API is being called by a mobile device?

  • In the OAuth case, should I perform (I don’t know how) silent calls to the OAuth provider to get back a new idToken and then request new tokens to my own API with it?

  • In the local case, should I keep user credentials stored locally? If so, how do I do that securely?

Some diagrams

These are the flows we’ve currently implemented, working as espected when the API is consumed by a webclient.

Local
Local flow


OAuth2.0
OAuth2.0 with Google provider flow

2016 – How to prevent SharePoint site page refresh itself when jquery .load is triggered?

I have a simple SharePoint site page (created in Site Page library). I added a simple jquery syntax here:

<script>
$(function() {
$("#button_overview").on("click", function(){   $("#homepagecontent").load("../description/overview.htm");   });

});
</script>

When I click the button, overview.htm is loaded for 1 sec and the entire page is refreshed. It cause the page render back to previous stage.

I have also tried .html("<p>hello</p>"). The result is “hello” show up for 1 sec and page is refreshed.

Is it default SharePoint behavior? How can I work around it?

javascript – Como hacer que un boton en react no se ralice onclick al hacer refresh

Problema: Tengo un botón que su función es hacer un logout, pero cuando inicio sesión como la página realiza un autorefresh de esta, automáticamente se pulsa y realiza el logout, es decir no permite loguearse a la gente porque las desloguea automáticamente en cuanto carga la otra página con el botón de logout.

return (
      <div className="App container">
        <div className="justify-content-center row">
          <h1 style={{ color: "white" }}>Bienvenido</h1>
        </div>
        <div className="justify-content-center row">
            <button
              type='button'
              className="btn btn-warning"
              onClick={setUserInfo(null)}
            >
              Logout
            </button>
        </div>
      </div>
    );
    
  }

  return (
    <div className="App container">
      <div className="justify-content-center row">
        <h1 style={{ color: "white" }}>Inicio de sesion</h1>
      </div>
      <Link to="/Register" className="nav-item nav-link active">
        Registro
      </Link>
      <div className="justify-content-center row">
        <form className="mt-5" onSubmit={handleLogin}>
          <label>
            <p>Username</p>
            <input required type="text" onChange={(e) => setUsuario(e.target.value)} />
          </label>
          <label>
            <p>Password</p>
            <input
              required
              type="password"
              onChange={(e) => setPassword(e.target.value)}
            />
          </label>
          <div>
            <button type='button' className="btn btn-success" type="submit">
              Iniciar Sesión
            </button>
          </div>
        </form>
      </div>
    </div>
  );

magento2 – Magento 2 – Pagination not refresh cache

I’m on the category page. When I click on the pagination number, for example the number 2 with the link “www.magento2.com/category?p=2”, I see that when clicked the page is never completely refreshed and therefore the cache is not updated.

I tried in my list.phtml file to insert this script but it doesn’t work:

<script>
    require(('jquery'), function($){
        $( ".page-layout-ricerca .items.pages-items li.item a" ).bind( "click", function(e) {
            e.preventDefault();
            location.href = $(this).attr("href");
        });
    });
</script>

How can I refres the whole page when I click on the pagination number every time?

c# – WPF (MVVM) – ObservableCollection does not immediately refresh DataGrid + is this adhering to MVVM design pattern?

Hello!

I am very confused.

I am building a WPF application, trying to use the MVVM design pattern. It’s fascinating and rewarding, even though it seems overly complex at times. I am new to programming, and I’ve only really dabbled in WinForms before this.

I’ve been through so many changes and adaptations, by experimenting and trying to implement solutions people provide me with, that I’ve sort of lost grip of everything I feel.

My application consists of the following (I am going to be thorough, because not being thorough is what got me into trouble in the first place):

ViewModels:
BaseViewModel.cs
MainViewModel.cs
AddViewModel.cs

Models:
ConnectionString.cs
LicenseHolder.cs
UserInfo.cs

Views:
HomeWindow.xaml
LicenseHolderProfileWindow.xaml
LicenseHoldersWindow.xaml
LoginScreenWindow.xaml
NewLicenseHolderWindow.xaml

Application flow:
LoginScreen is naturally the first window that opens, once you log in, you end up at the HomeWindow, which is basically just buttons leading to the different parts of the application (which only one of those is under development at the moment). I click a button to go to the LicenseHoldersWindow, which contains a DataGrid. The DataGrid is populated by a SQL server table, bound to an ObservableCollection. And here is where the tomfoolery begins.
See, at the moment, I just want to do a few simple things, which was fairly easy to get to work in WinForms, but proving quite the challenge in WPF.

Firstly: I want the DataGrid to automatically get the data from the server without having to press a button of any sort. This currently works.

Secondly: I want to be able to delete rows by clicking a button. This currently works.

Thirdly: I want to be able to add rows, by clicking a button -> opening a new window (NewLicenseHolderWindow) -> filling out TextBoxes, clicking a save button (window closes) -> voilà – DataGrid is updated! THIS DOES NOT WORK.
If I want the new row to appear in the DataGrid, I have to re-open the window.
This angers me tremendously.

Fourthly(?): I also tried implementing the function to select a DataGrid row, clicking a button -> opening a new window (LicenseHolderProfileWindow), and have the TextBoxes therein be populated by the data in the selected row. This kind of does’nt work.
Most of the TextBoxes are populated as they should, but some are missing, and some are misplaced.
Injustice! Definitively some issues with DataBinding, but I have been unsuccessful in finding out just what. They all seem to be bound the same, with no typos, yet only some of them come out right.

I am going to post most of my code, and am very grateful for any who read it all and try to understand it.

In addition to the specific issues I’ve listed, I am also very interested in streamlining
my application. I want it to fully adhere to the MVVM design pattern. I want it to be slim, not bulky, I want it to be as petite as it possibly can be. I feel like I am using far to much code-lines, and to many .cs files. Isn’t it possible to just use one ViewModel? As you will see in my code below, my ConnectionString, and some arbritary code to drag the entered UserName with me to correctly label the logout tag, which is the users e-mail address. I feel like that’s not correctly done. Also, the LoginScreen.xaml is not built up correctly, I am aware of this, but I don’t want to overstay my welcome – it’s a issue I’ll handle another day (but by all means, if anyone is feeling adventurous, I’ll accept any pointers regarding that one aswell).

My code follows, with some comments under each block.

–> ConnectionString.cs – just my connection string…

–> LicenseHolder.cs – my holder class, the getters/setters for the DataGrid columns.

namespace Ridel.Hub.Model {

    public class LicenseHolder {

        public int ID { get; set; }
        public string Foretaksnavn { get; set; }
        public string Foretaksnummer { get; set; }
        public string Adresse { get; set; }
        public int Postnummer { get; set; }
        public string Poststed { get; set; }
        public string BIC { get; set; }
        public string IBAN { get; set; }
        public string Kontakt { get; set; }
        public string Epost { get; set; }
        public string Tlf { get; set; }
        public string Kontonummer { get; set; }
    }
}

UserInfo.cs – simple class to bring with me the e-mail address of the logged in user to fill a label used as a ‘Log out’-button.

namespace Ridel.Hub {

    public class UserInfo {

        private const string userNameString = "";

        public static string UserName { get; set; } = userNameString;
    }
}

–> MainViewModel

using System;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight.CommandWpf;
using Ridel.Hub.Model;

namespace Ridel.Hub.ViewModel {

    public class MainViewModel : AddViewModel, INotifyPropertyChanged {

        public MainViewModel() {

            FillDataGridLicenseHolders();
        }

        // This method triggers when the user clicks the log out button (which is their e-mail address)
        public static void CloseAllWindowsExceptLoginScreen() {

            Application.Current.Windows
                .Cast<Window>()
                .Where(w => w is not LoginScreenWindow)
                .ToList()
                .ForEach(w => w.Close());

            MainViewModel viewModel = new MainViewModel();
            LoginScreenWindow loginScreen = new LoginScreenWindow(viewModel);
            loginScreen.Show();
        }

        public void FillDataGridLicenseHolders() {

            try {

                using (SqlConnection sqlCon = new(ConnectionString.connectionString))
                using (SqlCommand sqlCmd = new("select * from tblLicenseHolder", sqlCon))
                using (SqlDataAdapter sqlDaAd = new(sqlCmd))
                using (DataSet ds = new()) {

                    sqlCon.Open();
                    sqlDaAd.Fill(ds, "tblLicenseHolder");

                    foreach (DataRow dr in ds.Tables(0).Rows) {

                        // Adding the rows in the DataGrid to the ObservableCollection
                        LicenseHolders.Add(new LicenseHolder {

                            ID = Convert.ToInt32(dr(0).ToString()),
                            Foretaksnavn = dr(1).ToString(),
                            Foretaksnummer = dr(2).ToString(),
                            Adresse = dr(3).ToString(),
                            Postnummer = (int)dr(4),
                            Poststed = dr(5).ToString(),
                            BIC = dr(6).ToString(),
                            IBAN = dr(7).ToString(),
                            Kontakt = dr(8).ToString(),
                            Epost = dr(9).ToString(),
                            Tlf = dr(10).ToString(),
                            Kontonummer = dr(11).ToString()
                        });
                    }
                }
            } catch (Exception ex) {

                MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }

        private static bool RemoveFromDB(LicenseHolder myLicenseHolder) {

            string sqlString = $"Delete from tblLicenseHolder where ID = '{myLicenseHolder.ID}'";

            if (MessageBox.Show("Er du sikker på at du ønsker å slette valgt løyvehaver?", "Slett løyvehaver", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) {

                try {

                    using (SqlConnection sqlCon = new(ConnectionString.connectionString))
                    using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {

                        sqlCon.Open();
                        sqlCmd.ExecuteNonQuery();
                        return true;
                    }

                }
                catch {

                    return false;
                }

            } else {

                return false;
            }
        }

        private void RemoveLicenseHolderExecute(LicenseHolder myLicenseHolder) {

            bool result = RemoveFromDB(myLicenseHolder);
            if (result)
                LicenseHolders.Remove(myLicenseHolder);
        }

        private RelayCommand<LicenseHolder> _removeLicenseHoldersCommand;

        public RelayCommand<LicenseHolder> RemoveLicenseHoldersCommand => _removeLicenseHoldersCommand
            ??= new RelayCommand<LicenseHolder>(RemoveLicenseHolderExecute, RemoveLicenseHolderCanExecute);

        private bool RemoveLicenseHolderCanExecute(LicenseHolder myLicenseHolder) {

            return LicenseHolders.Contains(myLicenseHolder);
        }   
    }
}

–> AddViewModel (this is newly added, based on some feed-back I got, and it was at this point I felt things really got out of hand

using System;
using System.Collections.ObjectModel;
using System.Data.SqlClient;
using System.Windows;
using System.Windows.Input;
using GalaSoft.MvvmLight.CommandWpf;
using Ridel.Hub.Model;

namespace Ridel.Hub.ViewModel {

    public class AddViewModel : BaseViewModel {

        public ObservableCollection<LicenseHolder> LicenseHolders { get; set; }

        public ICommand RefreshCommand { get; private set; }

        public AddViewModel() {

            RefreshCommand = new RelayCommand(this.ExecuteRefreshCommand);
            LicenseHolders = new ObservableCollection<LicenseHolder>();
        }

        private string _foretaksnavn;
        public string Foretaksnavn {

            get { return _foretaksnavn; }
            set { SetValue(ref _foretaksnavn, value); }
        }

        private string _foretaksnummer;
        public string Foretaksnummer {

            get { return _foretaksnummer; }
            set { SetValue(ref _foretaksnummer, value); }
        }

        private string _adresse;
        public string Adresse {

            get { return _adresse; }
            set { SetValue(ref _adresse, value); }
        }

        private int _postnummer;
        public int Postnummer {

            get { return _postnummer; }
            set { SetValue(ref _postnummer, value); }
        }

        private string _poststed;
        public string Poststed {

            get { return _poststed; }
            set { SetValue(ref _poststed, value); }
        }

        private string _bic;
        public string BIC {

            get { return _bic; }
            set { SetValue(ref _bic, value); }
        }

        private string _iban;
        public string IBAN {

            get { return _iban; }
            set { SetValue(ref _iban, value); }
        }

        private string _kontakt;
        public string Kontakt {

            get { return _kontakt; }
            set { SetValue(ref _kontakt, value); }
        }

        private string _epost;
        public string Epost {

            get { return _epost; }
            set { SetValue(ref _epost, value); }
        }

        private string _tlf;
        public string Tlf {

            get { return _tlf; }
            set { SetValue(ref _tlf, value); }
        }

        private string _kontonummer;
        public string Kontonummer {

            get { return _kontonummer; }
            set { SetValue(ref _kontonummer, value); }
        }

        private void ExecuteRefreshCommand() {

            string sqlString = "insert into tblLicenseHolder (Foretaksnavn, Foretaksnummer, Adresse, Postnummer, Poststed, BIC, IBAN, Kontakt, Epost, Tlf, Kontonummer) " +
                "values (@Foretaksnavn, @Foretaksnummer, @Adresse, @Postnummer, @Poststed, @BIC, @IBAN, @Kontakt, @Epost, @Tlf, @Kontonummer)";

            if (Foretaksnavn == null || Foretaksnummer == null || Adresse == null 
                || Postnummer == 0 || Poststed == null || BIC == null || IBAN == null 
                || Kontakt == null || Epost == null || Tlf == null || Kontonummer == null) {

                MessageBox.Show("Fyll ut alle feltene.");

            } else {

                LicenseHolders = new ObservableCollection<LicenseHolder>();
                LicenseHolders.Add(new LicenseHolder() { Foretaksnavn = "Foretaksnavn" });
                LicenseHolders.Add(new LicenseHolder() { Foretaksnummer = "Foretaksnummer" });
                LicenseHolders.Add(new LicenseHolder() { Adresse = "Adresse" });
                LicenseHolders.Add(new LicenseHolder() { Postnummer = Postnummer });
                LicenseHolders.Add(new LicenseHolder() { Poststed = "Poststed" });
                LicenseHolders.Add(new LicenseHolder() { BIC = "BIC" });
                LicenseHolders.Add(new LicenseHolder() { IBAN = "IBAN" });
                LicenseHolders.Add(new LicenseHolder() { Kontakt = "Kontakt" });
                LicenseHolders.Add(new LicenseHolder() { Epost = "Epost" });
                LicenseHolders.Add(new LicenseHolder() { Tlf = "Tlf" });
                LicenseHolders.Add(new LicenseHolder() { Kontonummer = "Kontonummer" });

                try {

                    using (SqlConnection sqlCon = new(ConnectionString.connectionString))
                    using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {

                        sqlCon.Open();
                        sqlCmd.Parameters.AddWithValue("@Foretaksnavn", Foretaksnavn.ToString());
                        sqlCmd.Parameters.AddWithValue("@Foretaksnummer", Foretaksnummer.ToString());
                        sqlCmd.Parameters.AddWithValue("@Adresse", Adresse.ToString());
                        sqlCmd.Parameters.AddWithValue("@Postnummer", Convert.ToInt32(Postnummer.ToString()));
                        sqlCmd.Parameters.AddWithValue("@Poststed", Poststed.ToString());
                        sqlCmd.Parameters.AddWithValue("@BIC", BIC.ToString());
                        sqlCmd.Parameters.AddWithValue("@IBAN", IBAN.ToString());
                        sqlCmd.Parameters.AddWithValue("@Kontakt", Kontakt.ToString());
                        sqlCmd.Parameters.AddWithValue("@Epost", Epost.ToString());
                        sqlCmd.Parameters.AddWithValue("@Tlf", Tlf.ToString());
                        sqlCmd.Parameters.AddWithValue("@Kontonummer", Kontonummer.ToString());
                        sqlCmd.ExecuteNonQuery();
                        MessageBox.Show("Ny løyvehaver lagret.");
                    }
                }
                catch (Exception ex) {

                    MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
        }
    }
}

I am especially uncertain about how I’ve strutured the ExecuteRefreshCommand()-method.
The addition to the server is no problem, but adding to the ObservableCollection is not happening. Hopefully, there is a way to simplify and compact those two tasks into one: add to server & update ObservableCollection (do I need to add each item?!). Also, the getters/setters strings seems redundant, can’t I get and set what I need using the LicenseHolder.cs model class?

->BaseViewModel

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Ridel.Hub.ViewModel {

    public abstract class BaseViewModel : INotifyPropertyChanged {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged((CallerMemberName) string propertyName = null) {

            var handler = PropertyChanged;
            if (handler != null) {

                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected bool SetValue<T>(ref T storage, T value, (CallerMemberName) string propertyName = null) {

            if (Equals(storage, value)) return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}

I will omit the Windows which are irrelevant (at least to my understanding).
I am only posting the code-behind and the XAML from LicenseHoldersWindow, NewLicenseHolderWindow and LicenseHolderProfileWindow. I’ll trim away some of the XAML to make it somewhat readable.

–> LicenseHoldersWindow

<Window
    x:Class="Ridel.Hub.LicenseHoldersWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Ridel.Hub"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:MainViewModel}"
    ShowInTaskbar="False"
    mc:Ignorable="d">

    <Canvas Margin="10,10,10,10">

        <Button
            x:Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />

        <Button
            x:Name="btnProfile"
            Background="#48bb88"
            Content="Open profile"
            Style="{DynamicResource ButtonWithRoundCornersGreen}"
            Visibility="Visible" Click="btnProfile_Click" />

        <Button
            x:Name="btnNew"     
            Click="btnNew_Click"
            Content="New licenseholder"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />

        <Button
            x:Name="btnDelete"
            Command="{Binding RemoveLicenseHoldersCommand}"
            CommandParameter="{Binding SelectedItem, ElementName=dgLicenseHolder}"
            Content="Delete licenseholder"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />

        <DataGrid
            x:Name="dgLicenseHolder"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            IsReadOnly="True"
            SelectionChanged="dgLicenseHolder_SelectionChanged"
            ItemsSource="{Binding LicenseHolders}"
            SelectionMode="Single">

            <DataGrid.Columns>
                <DataGridTextColumn
                    Binding="{Binding Path=ID}"
                    Header="ID"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Width="310"
                    Binding="{Binding Path=Foretaksnavn}"
                    Header="Foretaksnavn"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    IsReadOnly="True"
                    Visibility="Visible" />
                <DataGridTextColumn
                    Binding="{Binding Path=Foretaksnummer}"
                    Header="Foretaksnummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Adresse}"
                    Header="Adresse"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Postnummer}"
                    Header="Postnummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Width="*"
                    Binding="{Binding Path=Poststed}"
                    Header="Poststed"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    IsReadOnly="True"
                    Visibility="Visible" />
                <DataGridTextColumn
                    Binding="{Binding Path=BIC}"
                    Header="BIC"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=IBAN}"
                    Header="IBAN"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Kontakt}"
                    Header="Kontakt"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Epost}"
                    Header="Epost"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Tlf}"
                    Header="Tlf"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Kontonummer}"
                    Header="Kontonummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
            </DataGrid.Columns>
        </DataGrid>
    </Canvas>
</Window>
using System.Windows;
using System.Windows.Controls;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class LicenseHoldersWindow : Window {

        public LicenseHoldersWindow(MainViewModel viewModel) {

            InitializeComponent();
            btnLogOut.Content = UserInfo.UserName;
            DataContext = viewModel;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }

        private void dgLicenseHolder_SelectionChanged(object sender, SelectionChangedEventArgs e) {

            btnProfile.IsEnabled = true;
            btnDelete.IsEnabled = true;
        }

        private void btnNew_Click(object sender, RoutedEventArgs e) {

            NewLicenseHolderWindow nlhw = new NewLicenseHolderWindow();
            nlhw.ShowDialog();
        }

        private void btnProfile_Click(object sender, RoutedEventArgs e) {

            if (this.dgLicenseHolder.SelectedItems.Count == 1) {

                LicenseHolderProfileWindow lpw = new LicenseHolderProfileWindow(null) { Owner = this, DataContext = dgLicenseHolder.SelectedItem };
                lpw.ShowDialog();
            }
        }
    }
}

–> NewLicenseHolderWindow

<Window
    x:Class="Ridel.Hub.NewLicenseHolderWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AddViewModel}"
    ResizeMode="NoResize"
    ShowInTaskbar="False"
    mc:Ignorable="d">

    <Canvas Margin="10,10,42,10">
        <Button
            Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />
   
        <TextBox
            Name="txtKontakt"
            Text="{Binding Path=Kontakt}"/>
        <TextBox
            Name="txtTlf"
            Text="{Binding Path=Tlf}"/>
        <TextBox
            Name="txtEpost"
            Text="{Binding Path=Epost}"/>
        <TextBox
            Name="txtForetaksnavn"
            Text="{Binding Path=Foretaksnavn}" />
        <TextBox
            Name="txtForetaksnr"
            Text="{Binding Path=Foretaksnummer}"/>
        <TextBox
            Name="txtAdresse"
            Text="{Binding Path=Adresse}"/>
        <TextBox
            Name="txtPoststed"
            Text="{Binding Path=Poststed}"/>
        <TextBox
            Name="txtPostnummer"
            Text="{Binding Path=Postnummer}"/>
        <TextBox
            Name="txtBIC"
            Text="{Binding Path=BIC}"/>
        <TextBox
            Name="txtIBAN"
            Text="{Binding Path=IBAN}"/>
        <TextBox
            Name="txtKontonr"
            Text="{Binding Path=Kontonummer}"/>

        <Button
            Name="btnSave"
            Command="{Binding Path=RefreshCommand}"
            Content="Save"
            Style="{DynamicResource ButtonWithRoundCornersGreen}">
        </Button>
    </Canvas>
</Window>
using System.ComponentModel;
using System.Linq;
using System.Windows;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class NewLicenseHolderWindow : Window, INotifyPropertyChanged {

        public event PropertyChangedEventHandler PropertyChanged;

        public NewLicenseHolderWindow() {

            InitializeComponent();
            btnLogOut.Content = UserInfo.UserName;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }
    }
}

–>LicenseHolderProfileWindow

<Window
    x:Class="Ridel.Hub.LicenseHolderProfileWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AddViewModel}"
    mc:Ignorable="d">

    <Canvas Margin="10,10,42,10">
        <Button
            Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />

        <TextBox
            Name="txtKontakt"
            Text="{Binding Kontakt, Mode=TwoWay, FallbackValue=Kontakt}" />
        <TextBox
            Name="txtTlf"
            Text="{Binding Tlf, Mode=TwoWay, FallbackValue=Tlf}" />
        <TextBox
            Name="txtEpost"
            Text="{Binding Epost, Mode=TwoWay, FallbackValue=Epost}" />
        <TextBox
            Name="txtForetaksnavn"
            Text="{Binding Foretaksnavn, Mode=TwoWay, FallbackValue=Foretaksnavn}" />
        <TextBox
            Name="txtForetaksnr"
            Text="{Binding Foretaksnummer, Mode=TwoWay, FallbackValue=Foretaksnummer}" />
        <TextBox
            Name="txtAdresse"
            Text="{Binding Adresse, Mode=TwoWay, FallbackValue=Adresse}" />
        <TextBox
            Name="txtPoststed"
            Text="{Binding Poststed, Mode=TwoWay, FallbackValue=Poststed}" />
        <TextBox
            Name="txtPostnummer"  
            Text="{Binding Postnummer, Mode=TwoWay, FallbackValue=Postnummer}" />
        <TextBox
            Name="txtBIC"
            Text="{Binding BIC, Mode=TwoWay, FallbackValue=BIC}" />
        <TextBox
            Name="txtIBAN"
              Text="{Binding IBAN, Mode=TwoWay, FallbackValue=IBAN}" />
        <TextBox
            Name="txtKontonr"
            IsReadOnly="True"
            Text="{Binding Kontonummer, Mode=TwoWay, FallbackValue=Kontonummer}" />

        <Button
            Name="btnLagre"           
            Click="btnLagre_Click"
            Command="{Binding RefreshCommand}"
            Content="Lagre"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />
     </Canvas>
</Window>
using System.Windows;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class LicenseHolderProfileWindow : Window {

        public LicenseHolderProfileWindow(AddViewModel viewModel) {

            InitializeComponent();
            DataContext = viewModel;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }

        private void btnSave_Click(object sender, RoutedEventArgs e) {

            btnAllowEdit.IsEnabled = true;
            Close();
        }
    }
}

Thankful if anyone read this far, and even more thankful if anyone decides to give me their 2-cents.