Tuesday, July 18, 2017

SharePoint 2016 (on prem) - HTTP 500 internal server error

I'm setting up a SharePoint 2016 site for a demo and discovered the pages don't display due to an HTTP 500 Internal Server Error.  However Central Administration works just fine.  Fortunately a Google search lead to this article from Cloudshare that contained the solution for me- https://www.cloudshare.com/blog/cloudshare/http-500-internal-server-error-explanation-how-to-fix  It pertains to SP2013, but is exactly the same in SP2016.  Basically the SecurityTokenServiceApplicationPool's security context needed to be updated.

Thanks Cloudshare!

Saturday, March 25, 2017

WPF/MVVM viewing and editing data in a many-to-many relationship (Part 2 of 2)

This is a continuation of a previous post where I explained my scenario and how I displayed data in a many-to-many relationship.  Now I'll explain how I ended up editing and saving.  It seems a bit more complicated than it should be, but it works.

Editing

I have two objects named Racers and Divisions. One racer can be in zero or more divisions and one division can contain zero or more racers.  I'm editing the relationship on a Racer maintenance form where a racer's divisions are selected in a checkbox list.  See the previous post for details.

View Model

To accommodate this I have two commands in my Maintain Racer view model, one for adding a division and one for removing a division.  And a keep the original list of racer divisions in case the user cancels.  Here are the relevant parts of the view model: 
        private List<Division> _originalRacerDivisions;

        public ICommand AddDivisionCommand { get; set; }
        public ICommand RemoveDivisionCommand { get; set; }

        // Constructor
        public RacerDetailViewModel(IDerbyDataService derbyDataService)
        {
            ... snip ...
            AddDivisionCommand = new CustomCommand(AddDivision, CanAddRemoveDivision);
            RemoveDivisionCommand = new CustomCommand(RemoveDivision, CanAddRemoveDivision);
            ... snip ...
        }

        private void LoadRacer(Racer racer)
        {
            ... snip ...
            _originalRacerDivisions = racer.Divisions;
            ... snip ...
        }
 
        private void AddDivision(object obj)
        {
            if (!(obj is Division))
                throw new ArgumentException("Invalid division");

            var divisionToAdd = (Division)obj;
            var racerDivisions = RacerDivisions;

            racerDivisions.Add(divisionToAdd);
            RacerDivisions = racerDivisions;
        }

        private void RemoveDivision(object obj)
        {
            if (!(obj is Division))
                throw new ArgumentException("Invalid division");

            var divisionToRemove = (Division)obj;
            var racerDivisions = RacerDivisions;

            racerDivisions.Remove(divisionToRemove);
            RacerDivisions = racerDivisions;
        }

        private bool CanAddRemoveDivision(object obj)
        {
            return true;
        }
    }
}


View

In the view I have a template column with a checkbox.  I used this instead of a checkbox column because a checkbox column requires two clicks- one to select the row and a second to change the value.  This way only one click is needed.

There are two triggers- one handles the Checked event and calls the AddDivision command, and the other handles the Unchecked event and called RemoveDivision command.
<DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">
                                    <CheckBox.IsChecked>
                                        <MultiBinding Converter="{StaticResource localDivisionToBooleanConverter}" 
                                                      Mode="OneWay">
                                            <Binding Path="."></Binding>
                                            <Binding Path="DataContext.RacerDivisions" 
                                                     RelativeSource="{RelativeSource AncestorType=Window}"></Binding>
                                        </MultiBinding>
                                    </CheckBox.IsChecked>
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="Checked">
                                            <i:InvokeCommandAction Command="{Binding DataContext.AddDivisionCommand, RelativeSource={RelativeSource AncestorType=Window}}" 
                                                                   CommandParameter="{Binding Path=.}" />
                                        </i:EventTrigger>
                                        <i:EventTrigger EventName="Unchecked">
                                            <i:InvokeCommandAction Command="{Binding DataContext.RemoveDivisionCommand, RelativeSource={RelativeSource AncestorType=Window}}" 
                                                                   CommandParameter="{Binding Path=.}" />
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </CheckBox>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

Cancelling

If the user decides to cancel, the racer's divisions need to be set back to their original values:
private void CancelRacer(object obj)
        {
            racer.Divisions = _originalRacerDivisions;
            ... snip ...
        }

Thursday, March 16, 2017

WPF/MVVM viewing and editing data in a many-to-many relationship (Part 1 of 2)

In the WPF/MVVM world some things seem to be a lot more complicated than they should be.  One of those things is presenting and editing data in a many-to-many relationship.  Once again, thanks to Google for leading to this article that was the starting point for of my solution- https://social.technet.microsoft.com/wiki/contents/articles/20719.wpf-displaying-and-editing-many-to-many-relational-data-in-a-datagrid.aspx

My Scenario

I have two objects named Racers and Divisions.  One racer can be in zero or more divisions and one division can contain zero or more racers.  The data is edited on a Racer maintenance form that looks like this:
The corresponding database tables look like this:


These are my model classes.  Note that there are just two classes- Racer and Division.  The navigation properties (Racer.Divisions and Divisions.Racers) are the link between them and are equivalent to the RacerDivisions link table in the database.
  public class Racer : ModelBase, IModificationHistory  
   {  
     public Racer()  
     {  
       Divisions = new List<Division>();   
     }  
     private int racerId;  
     private int carNumber;  
     private string carName;  
     private string ownerLastName;  
     private string ownerFirstName;  
     private List<Division> divisions;   
     private DateTime dateModified;  
     private DateTime dateCreated;  

     public int RacerId  
     {  
       get { return racerId; }  
       set  
       {  
         if (value == racerId) return;  
         racerId = value;  
         RaisePropertyChanged("RacerId");  
       }  
     }  

     // The other getters/setters here
   }

   public class Division : ModelBase, IModificationHistory
    {
        public Division()
        {
            Racers = new List();
        }

        private int divisionId;
        private int sequence;
        private string name;
        private string logoPath;
        private bool includeInChampionship;
        private bool isChampionship;
        private List racers;
        private DateTime dateModified;
        private DateTime dateCreated;

        public int DivisionId
        {
            get { return divisionId; }
            set
            {
                divisionId = value;
                RaisePropertyChanged("DivisionId");
            }
        }

        // The other getters/setters here
    }


Showing the Data

Like the TechNet article, I am showing all the Divisions in a DataGrid with a check box column representing the divisions the racer is a member of (ie. is linked to).  So in my viewmodel I expose a list of all Divisions and a list of the Racer's Divisions (from the Racer object's graph- Racer.Divisions).  Here are the relevant viewmodel snippets:
   public class RacerDetailViewModel : ViewModelBase, IDataErrorInfo  
   {  
     private List<Division> _divisions;      
     private Racer _selectedRacer { get; set; }   
     
     // Various properties exposing Racer data to the view
     
     // The list of all Divisions
     public List<Division> Divisions  
     {  
       get { return _divisions; }  
     }  

     // The Racer Instance's Divisions 
     public ObservableCollection<Division> RacerDivisions  
     {  
       get { return _selectedRacer.Divisions.ToObservableCollection(); }  
       set  
       {  
         _selectedRacer.Divisions = value.ToList();  
         SetRacerDirty();  
         RaisePropertyChanged("Divisions");  
       }  
     }  

     // Other unrelated parts of the viewmodel (constructor, command handlers, etc.)     
 
   }  

The checkboxes need a boolean value to bind to.  I have a converter for this that takes two parameters: a Division object and a list of Racer.Divisions.  If Racer.Divisions contains the Division, it returns True, and if not- False.
  class DivisionToBooleanConverter : IMultiValueConverter  
   {  
     public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)  
     {  
       if (!(values[0] is Division))  
         throw new ArgumentException("DivisionToBooleanConverter- First arg must be Division");  
       if (!(values[1] is ObservableCollection<Division>))  
         throw new ArgumentException("DivisionToBooleanConverter- Second arg must be RacerDivisions.");  
       var division = (Division)values[0];  
       var racerDivisions = (ObservableCollection<Division>)values[1];  
       return racerDivisions.Contains(division);  
     }  
     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)  
     {  
       throw new NotImplementedException();  
     }  
   }  

And finally, the WPF DataGrid that shows the data.  It is bound to the list of all Divisions.  I put the checkboxes in a template column because in a regular checkbox column the checkbox has to be clicked twice to change its value.  The current division and list of Racer's divisions are passed to the converter to populate the row's checkbox.
 <DataGrid Grid.Row="4" Grid.Column="1" Margin="5" ItemsSource="{Binding Divisions}"   
          AutoGenerateColumns="False" CanUserAddRows="False" HeadersVisibility="None">  
       <DataGrid.Columns>  
         <DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn>  
         <DataGridTemplateColumn>  
           <DataGridTemplateColumn.CellTemplate>  
             <DataTemplate>  
               <Grid>  
                 <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">  
                   <CheckBox.IsChecked>  
                     <MultiBinding Converter="{StaticResource localDivisionToBooleanConverter}"   
                            Mode="OneWay">  
                       <Binding Path="."></Binding>  
                       <Binding Path="DataContext.RacerDivisions"   
                            RelativeSource="{RelativeSource AncestorType=Window}"></Binding>  
                     </MultiBinding>  
                   </CheckBox.IsChecked>  
                 </CheckBox>  
               </Grid>  
             </DataTemplate>  
           </DataGridTemplateColumn.CellTemplate>  
         </DataGridTemplateColumn>  
       </DataGrid.Columns>  
     </DataGrid>  

And there you have it!  Next I'll explain how the data is edited and saved.  That will be in a new post because this one is long enough.

Sunday, March 12, 2017

WPF/MVVM - Validating ViewModels with IDataErrorInfo and models with annotations

I'm working on a personal WPF/MVVM project where I need validations at both the View Model and Model level.  For business rule validation I decided to implement the IDataErrorInfo interface in my view models.  It works pretty well and it is easy to find examples of how to do it.  However in my case I also have basic validations (like required fields, string length limits, etc.) in Annotations at the model level.  This is necessary because I'm using Entity Framework 6- Code First to generate my database.  The hard part was combining both levels of validation.  Here's how I ended up doing it:

All my model classes inherit from a base class that implements INotifyPropertyChanged and IDataErrorInfo.  OnValidate returns validation errors from the annotations.  Plenty of examples how to do this- just google IDataErrorInfo Annotations.

    public class ModelBase : INotifyPropertyChanged, IDataErrorInfo
    {
        #region " INotifyPropertyChanged "
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region " IDataErrorInfo "
        public string this[string propertyName]
        {
            get
            {
                return OnValidate(propertyName);
            }
        }

        /// <summary>
        /// Validates current instance properties using Data Annotations.
        /// </summary>
        /// <param name=“propertyName”>This instance property to validate.</param>
        /// <returns>Relevant error string on validation failure or <see cref=“System.String.Empty”/> on validation success.</returns>
        private string OnValidate(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName))
                throw new ArgumentException("Property may not be null or empty", propertyName);

            string error = string.Empty;

            var value = this.GetType().GetProperty(propertyName).GetValue(this, null);
            var results = new List<ValidationResult>();

            var context = new ValidationContext(this, null, null) { MemberName = propertyName };

            var result = Validator.TryValidateProperty(value, context, results);

            if (!result)
            {
                var validationResult = results.First();
                error = validationResult.ErrorMessage;
            }
            return error;
        }

        public string Error
        {
            get
            {
                throw new NotSupportedException("IDataErrorInfo.Error is not supported, use IDataErrorInfo.this[propertyName] instead.");
            }
        }
        #endregion
    }

The implementation in my model classes looks more or less like this:

    public class MyClass: ModelBase
    {
        private string someProperty;
       
        [Required]
        [StringLength(255, ErrorMessage = "Some Property maximum length is 255 characters")]
        public string SomeProperty
        {
            get { return someProperty; }
            set
            {
                if (value == someProperty) return;
                someProperty= value;
                RaisePropertyChanged("SomeProperty");
            }
        }
    }

And then in my view models I also implement IDataErrorInfo.  I first perform the view model validations, then if there are no errors I go to the model's IDataErrorInfo's implementations and check for errors there.  The basic idea came from http://stackoverflow.com/questions/13113779/implementing-idataerrorinfo-in-a-view-model

    public class MyViewModel: IDataErrorInfo
    {
        private MyClass _myClass { get; set; }

        public string SomeProperty
        {
            get { return _myClass.SomeProperty; }
            set
            {
                _myClass.SomeProperty= value;
                RaisePropertyChanged("SomeProperty");
            }
        }

        #region " Implementation of IDataErrorInfo "

        public string Error
        {
            get { throw new NotSupportedException("Not supported"); }
        }

        // Put business rule validation here
        public string this[string propertyName]
        {
            get
            {
                if (propertyName.Equals("SomeProperty"))
                {
                    if (SomeProperty == "FooBar")
                        return "SomeProperty cannot be FooBar.";
                }

                // If we get to here, ViewModel validation passed.  So do the Model validations- 
                return _selectedRacer[propertyName];
            }
        }
    #endregion
    }

And finally, the binding in the view looks like this:

<TextBox Text="{Binding SomeProperty, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}">