REST to a .Net Standard Library

Test REST in discord bot and WPF
Small improvements
This commit is contained in:
2019-03-16 12:22:52 +01:00
parent 081d9ae893
commit 2fe08f938a
22 changed files with 423 additions and 78 deletions

View File

@@ -0,0 +1,173 @@
using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace LaDOSE.DesktopApp.Behaviors
{
public class TextBoxInputRegExBehaviour : Behavior<TextBox>
{
#region DependencyProperties
public static readonly DependencyProperty RegularExpressionProperty =
DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*"));
public string RegularExpression
{
get { return (string)GetValue(RegularExpressionProperty); }
set { SetValue(RegularExpressionProperty, value); }
}
public static readonly DependencyProperty MaxLengthProperty =
DependencyProperty.Register("MaxLength", typeof(int), typeof(TextBoxInputRegExBehaviour),
new FrameworkPropertyMetadata(int.MinValue));
public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
set { SetValue(MaxLengthProperty, value); }
}
public static readonly DependencyProperty EmptyValueProperty =
DependencyProperty.Register("EmptyValue", typeof(string), typeof(TextBoxInputRegExBehaviour), null);
public string EmptyValue
{
get { return (string)GetValue(EmptyValueProperty); }
set { SetValue(EmptyValueProperty, value); }
}
#endregion
/// <summary>
/// Attach our behaviour. Add event handlers
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewTextInput += PreviewTextInputHandler;
AssociatedObject.PreviewKeyDown += PreviewKeyDownHandler;
DataObject.AddPastingHandler(AssociatedObject, PastingHandler);
}
/// <summary>
/// Deattach our behaviour. remove event handlers
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewTextInput -= PreviewTextInputHandler;
AssociatedObject.PreviewKeyDown -= PreviewKeyDownHandler;
DataObject.RemovePastingHandler(AssociatedObject, PastingHandler);
}
#region Event handlers [PRIVATE] --------------------------------------
void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
{
string text;
if (this.AssociatedObject.Text.Length < this.AssociatedObject.CaretIndex)
text = this.AssociatedObject.Text;
else
{
// Remaining text after removing selected text.
string remainingTextAfterRemoveSelection;
text = TreatSelectedText(out remainingTextAfterRemoveSelection)
? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text)
: AssociatedObject.Text.Insert(this.AssociatedObject.CaretIndex, e.Text);
}
e.Handled = !ValidateText(text);
}
/// <summary>
/// PreviewKeyDown event handler
/// </summary>
void PreviewKeyDownHandler(object sender, KeyEventArgs e)
{
if (string.IsNullOrEmpty(this.EmptyValue))
return;
string text = null;
// Handle the Backspace key
if (e.Key == Key.Back)
{
if (!this.TreatSelectedText(out text))
{
if (AssociatedObject.SelectionStart > 0)
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart - 1, 1);
}
}
// Handle the Delete key
else if (e.Key == Key.Delete)
{
// If text was selected, delete it
if (!this.TreatSelectedText(out text) && this.AssociatedObject.Text.Length > AssociatedObject.SelectionStart)
{
// Otherwise delete next symbol
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, 1);
}
}
if (text == string.Empty)
{
this.AssociatedObject.Text = this.EmptyValue;
if (e.Key == Key.Back)
AssociatedObject.SelectionStart++;
e.Handled = true;
}
}
private void PastingHandler(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(DataFormats.Text))
{
string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
if (!ValidateText(text))
e.CancelCommand();
}
else
e.CancelCommand();
}
#endregion Event handlers [PRIVATE] -----------------------------------
#region Auxiliary methods [PRIVATE] -----------------------------------
/// <summary>
/// Validate certain text by our regular expression and text length conditions
/// </summary>
/// <param name="text"> Text for validation </param>
/// <returns> True - valid, False - invalid </returns>
private bool ValidateText(string text)
{
return (new Regex(this.RegularExpression, RegexOptions.IgnoreCase)).IsMatch(text) && (MaxLength == int.MinValue || text.Length <= MaxLength);
}
/// <summary>
/// Handle text selection
/// </summary>
/// <returns>true if the character was successfully removed; otherwise, false. </returns>
private bool TreatSelectedText(out string text)
{
text = null;
if (AssociatedObject.SelectionLength <= 0)
return false;
var length = this.AssociatedObject.Text.Length;
if (AssociatedObject.SelectionStart >= length)
return true;
if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length)
AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart;
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength);
return true;
}
#endregion Auxiliary methods [PRIVATE] --------------------------------
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Windows;
using Caliburn.Micro;
using LaDOSE.DesktopApp.Services;
using LaDOSE.DesktopApp.ViewModels;
using LaDOSE.REST;
namespace LaDOSE.DesktopApp
{
@@ -18,14 +20,19 @@ namespace LaDOSE.DesktopApp
protected override void Configure()
{
container = new SimpleContainer();
container.Singleton<IWindowManager, WindowManager>();
container.PerRequest<ShellViewModel>();
container.Singleton<RestService>();
container.PerRequest<ShellViewModel>();
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
@@ -44,6 +51,7 @@ namespace LaDOSE.DesktopApp
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
}

View File

@@ -66,8 +66,8 @@
<Reference Include="Caliburn.Micro.Platform.Core, Version=3.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.2.0\lib\net45\Caliburn.Micro.Platform.Core.dll</HintPath>
</Reference>
<Reference Include="RestSharp, Version=106.6.5.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.106.6.5\lib\net452\RestSharp.dll</HintPath>
<Reference Include="RestSharp, Version=106.6.9.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.106.6.9\lib\net452\RestSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -99,12 +99,12 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Behaviors\TextBoxInputRegExBehaviour.cs" />
<Compile Include="Behaviors\MultiSelectorBehaviours.cs" />
<Compile Include="Bootstrapper.cs" />
<Compile Include="Themes\LeftMarginMultiplierConverter.cs" />
<Compile Include="Themes\TreeViewItemExtensions.cs" />
<Compile Include="Utils\PhpSerialize.cs" />
<Compile Include="Services\RestService.cs" />
<Compile Include="UserControls\BookingUserControl.xaml.cs">
<DependentUpon>BookingUserControl.xaml</DependentUpon>
</Compile>
@@ -189,6 +189,10 @@
<Project>{61201da6-1bc9-4ba1-ac45-70104d391ecd}</Project>
<Name>LaDOSE.DTO</Name>
</ProjectReference>
<ProjectReference Include="..\LaDOSE.REST\LaDOSE.REST.csproj">
<Project>{692c2a72-ab7e-4502-bed8-aa2afa1761cb}</Project>
<Name>LaDOSE.REST</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="64x64.ico" />
@@ -208,5 +212,8 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,174 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Windows;
using LaDOSE.DTO;
using RestSharp;
using RestSharp.Authenticators;
using RestSharp.Serialization.Json;
using DataFormat = RestSharp.DataFormat;
namespace LaDOSE.DesktopApp.Services
{
public class RestService
{
public RestClient Client { get; set; }
public RestService()
{
#if DEBUG
MessageBox.Show("WAIT");
#endif
var appSettings = ConfigurationManager.AppSettings;
string url = (string) appSettings["ApiUri"];
string user = (string)appSettings["ApiUser"];
string password = (string) appSettings["ApiPassword"];
Client = new RestClient(url);
var restRequest = new RestRequest("users/auth", Method.POST);
restRequest.AddJsonBody(new { username = user, password = password });
var response = Client.Post(restRequest);
if (response.IsSuccessful)
{
JsonDeserializer d = new JsonDeserializer();
var applicationUser = d.Deserialize<ApplicationUser>(response);
Client.Authenticator = new JwtAuthenticator($"{applicationUser.Token}");
}
else
{
MessageBox.Show("Unable to contact services, i m useless, BYEKTHX","Error",MessageBoxButton.OK,MessageBoxImage.Error);
Application.Current.Shutdown(-1);
}
}
#region PostFix
private T Post<T>(string resource,T entity)
{
var json = new RestSharp.Serialization.Json.JsonSerializer();
var jsonD = new RestSharp.Serialization.Json.JsonDeserializer();
var request = new RestRequest();
request.Method = Method.POST;
request.Resource = resource;
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-type", "application/json");
request.Parameters.Clear();
request.AddParameter("application/json; charset=utf-8", json.Serialize(entity), ParameterType.RequestBody);
request.AddObject(entity);
var response = Client.Execute(request);
//var content = response.Content; // raw content as string
try
{
return jsonD.Deserialize<T>(response);
}
catch (Exception)
{
return default(T);
}
}
private R Post<P,R>(string resource, P entity)
{
var json = new RestSharp.Serialization.Json.JsonSerializer();
var jsonD = new RestSharp.Serialization.Json.JsonDeserializer();
var request = new RestRequest();
request.Method = Method.POST;
request.Resource = resource;
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-type", "application/json");
request.Parameters.Clear();
request.AddParameter("application/json; charset=utf-8", json.Serialize(entity), ParameterType.RequestBody);
//request.AddObject(entity);
var response = Client.Execute(request);
//var content = response.Content; // raw content as string
try
{
return jsonD.Deserialize<R>(response);
}
catch (Exception)
{
return default(R);
}
}
#endregion
#region WordPress
public List<WPEventDTO> GetEvents()
{
var restRequest = new RestRequest("/api/wordpress/WPEvent", Method.GET);
var restResponse = Client.Get<List<WPEventDTO>>(restRequest);
return restResponse.Data;
}
public string CreateChallonge(int gameId, int eventId)
{
var restRequest = new RestRequest($"/api/wordpress/CreateChallonge/{gameId}/{eventId}", Method.GET);
var restResponse = Client.Get(restRequest);
return restResponse.Content;
}
public string CreateChallonge2(int gameId, int eventId, List<WPUserDTO> optionalPlayers)
{
var restResponse = Post<List<WPUserDTO>,string>($"/api/wordpress/CreateChallonge/{gameId}/{eventId}",optionalPlayers);
return restResponse;
}
public bool RefreshDb()
{
var restRequest = new RestRequest("/api/Wordpress/UpdateDb", Method.GET);
var restResponse = Client.Get<bool>(restRequest);
return restResponse.Data;
}
public List<WPUserDTO> GetUsers(int wpEventId, int gameId)
{
var restRequest = new RestRequest($"/api/Wordpress/GetUsers/{wpEventId}/{gameId}", Method.GET);
var restResponse = Client.Get<List<WPUserDTO>>(restRequest);
return restResponse.Data;
}
public List<WPUserDTO> GetUsersOptions(int wpEventId, int gameId)
{
var restRequest = new RestRequest($"/api/Wordpress/GetUsersOptions/{wpEventId}/{gameId}", Method.GET);
var restResponse = Client.Get<List<WPUserDTO>>(restRequest);
return restResponse.Data;
}
#endregion
#region Games
public List<GameDTO> GetGames()
{
var restRequest = new RestRequest("/api/Game", Method.GET);
var restResponse = Client.Get<List<GameDTO>>(restRequest);
return restResponse.Data;
}
public GameDTO UpdateGame(GameDTO game)
{
return Post("Api/Game", game);
}
public bool DeleteGame(int gameId)
{
var restRequest = new RestRequest($"/api/Game/{gameId}", Method.DELETE);
var restResponse = Client.Execute(restRequest);
return restResponse.IsSuccessful;
}
#endregion
#region Events
#endregion
}
}

View File

@@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using Caliburn.Micro;
using LaDOSE.DesktopApp.Services;
using LaDOSE.DTO;
using LaDOSE.REST;
namespace LaDOSE.DesktopApp.ViewModels
{
@@ -16,19 +17,20 @@ namespace LaDOSE.DesktopApp.ViewModels
{
this.RestService = restService;
this.Games=new List<GameDTO>();
}
protected override void OnInitialize()
{
LoadGames();
this.CurrentGame = Games.First();
base.OnInitialize();
}
public void LoadGames()
{
this.Games.Clear();
this.Games = this.RestService.GetGames();
var gameDtos = this.RestService.GetGames().OrderBy(e=>e.Order).ToList();
this.Games = gameDtos;
NotifyOfPropertyChange("Games");
}
@@ -56,7 +58,8 @@ namespace LaDOSE.DesktopApp.ViewModels
public void Update()
{
this.RestService.UpdateGame(this.CurrentGame);
this.Games = RestService.GetGames();
LoadGames();
}
public void AddGame()
{

View File

@@ -1,8 +1,9 @@
using System;
using System.Configuration;
using System.Windows;
using System.Windows.Media.Imaging;
using Caliburn.Micro;
using LaDOSE.DesktopApp.Services;
using LaDOSE.REST;
namespace LaDOSE.DesktopApp.ViewModels
{
@@ -15,6 +16,16 @@ namespace LaDOSE.DesktopApp.ViewModels
this.DisplayName = "LaDOSE";
this.AppIcon = BitmapFrame.Create(Application.GetResourceStream(new Uri("/LaDOSE.DesktopApp;component/Resources/64x64.png",
UriKind.RelativeOrAbsolute)).Stream);
var appSettings = ConfigurationManager.AppSettings;
string url = (string)appSettings["ApiUri"];
string user = (string)appSettings["ApiUser"];
string password = (string)appSettings["ApiPassword"];
Uri uri = new Uri(url);
var restService = IoC.Get<RestService>();
restService.Connect(uri, user, password);
var wordPressViewModel = new WordPressViewModel(IoC.Get<RestService>());
ActivateItem(wordPressViewModel);
base.OnInitialize();

View File

@@ -8,9 +8,9 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Caliburn.Micro;
using LaDOSE.DesktopApp.Services;
using LaDOSE.DesktopApp.Utils;
using LaDOSE.DTO;
using LaDOSE.REST;
using Action = System.Action;
namespace LaDOSE.DesktopApp.ViewModels
@@ -169,7 +169,7 @@ namespace LaDOSE.DesktopApp.ViewModels
var reservation = SelectedWpEvent.WpBookings.FirstOrDefault();
var games = WpEventDeserialize.Parse(reservation.Meta);
GamesFound.Clear();
var foundGames = new List<GameDTO>();
if (games != null)
{
foreach (string wpTag in games.Select(e => e.Name))
@@ -178,14 +178,20 @@ namespace LaDOSE.DesktopApp.ViewModels
e.WordPressTag != null && e.WordPressTag.Split(';').Contains(wpTag));
if (foundGame != null)
{
if (!GamesFound.Contains(foundGame))
if (!foundGames.Contains(foundGame))
{
GamesFound.Add(foundGame);
foundGames.Add(foundGame);
}
}
}
}
var orderedEnumerable = foundGames.OrderBy(e => e.Order);
foreach (var gameDto in orderedEnumerable)
{
GamesFound.Add(gameDto);
}
NotifyOfPropertyChange(() => GamesFound);
}
@@ -209,8 +215,9 @@ namespace LaDOSE.DesktopApp.ViewModels
System.Windows.Input.Mouse.OverrideCursor = Cursors.Wait);
GamesFound = new ObservableCollection<GameDTO>();
this.Games = this.RestService.GetGames();
this.Events = this.RestService.GetEvents();
var events = this.RestService.GetEvents();
events.ForEach(e => e.WpBookings = e.WpBookings.OrderBy(x => x.WpUser.Name).ToList());
this.Events = events;
NotifyOfPropertyChange("Events");
Application.Current.Dispatcher.Invoke(() =>
System.Windows.Input.Mouse.OverrideCursor = null);

View File

@@ -4,6 +4,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:LaDOSE.DesktopApp.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviors="clr-namespace:LaDOSE.DesktopApp.Behaviors"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Row="4" Column="1">
@@ -19,7 +21,7 @@
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Id}"></Label>
<Label Content="{Binding Order}"></Label>
<Label> - </Label>
<Label Content="{Binding Name}"></Label>
</StackPanel>
@@ -37,6 +39,7 @@
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
@@ -51,11 +54,20 @@
<Label Grid.Row="2" Grid.Column="0">Name</Label>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=CurrentGame.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Label Grid.Row="3" Grid.Column="0">WpTag</Label>
<TextBox Grid.Row="4" Grid.ColumnSpan="2" Text="{Binding Path=CurrentGame.WordPressTag,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Label Grid.Row="5" Grid.Column="0">WpTagOs</Label>
<TextBox Grid.Row="6" Grid.ColumnSpan="2" Text="{Binding Path=CurrentGame.WordPressTagOs,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Button Grid.Row="7" Grid.ColumnSpan="2" x:Name="Update">Update</Button>
<Label Grid.Row="3" Grid.Column="0">Order</Label>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=CurrentGame.Order,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Behaviors>
<behaviors:TextBoxInputRegExBehaviour RegularExpression="^\d+$" MaxLength="9" EmptyValue="0">
</behaviors:TextBoxInputRegExBehaviour>
</i:Interaction.Behaviors>
</TextBox>
<Label Grid.Row="4" Grid.Column="0">WpTag</Label>
<TextBox Grid.Row="5" Grid.ColumnSpan="2" Text="{Binding Path=CurrentGame.WordPressTag,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Label Grid.Row="6" Grid.Column="0">WpTagOs</Label>
<TextBox Grid.Row="7" Grid.ColumnSpan="2" Text="{Binding Path=CurrentGame.WordPressTagOs,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Button Grid.Row="8" Grid.ColumnSpan="2" x:Name="Update">Update</Button>
</Grid>
</Grid>

View File

@@ -2,6 +2,6 @@
<packages>
<package id="Caliburn.Micro" version="3.2.0" targetFramework="net461" />
<package id="Caliburn.Micro.Core" version="3.2.0" targetFramework="net461" />
<package id="RestSharp" version="106.6.5" targetFramework="net461" />
<package id="RestSharp" version="106.6.9" targetFramework="net461" />
<package id="WPFThemes.DarkBlend" version="1.0.8" targetFramework="net461" />
</packages>