I'm learning WPF MVVM using Web API but I can't find any example about MVVM using a Web API to access database
I can load the data from database now but I can't use the "Save Employee" to call api to use post method.
The api is tested with postman and it works fine
I searched a lot for example but I can't found any similar example to my project.
View
<Window x:Class="WpfAppCallingAPI.View.MainWindow"
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:local="clr-namespace:WpfAppCallingAPI.View"
xmlns:APItest="clr-namespace:WpfAppCallingAPI.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!--<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.New"
Executed="NewCommand_Executed"
CanExecute="NewCommand_CanExecute"/>
</Window.CommandBindings>-->
<Grid>
<Label x:Name="lblEMPLOYEEID" Content="EMPLOYEEID" HorizontalAlignment="Left" Margin="28,10,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblNAME" Content="NAME" HorizontalAlignment="Left" Margin="28,41,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtEMPLOYEEID" Text="{Binding EMPLOYEE.EMPLOYEEID}" HorizontalAlignment="Left" Height="23" Margin="134,12,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txtNAME" Text="{Binding EMPLOYEE.NAME}" HorizontalAlignment="Left" Height="23" Margin="134,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Button x:Name="btnSave" Command="{Binding SaveCommand }" Content="Save" HorizontalAlignment="Left" Margin="134,189,0,0" VerticalAlignment="Top" Width="120"/>
<!--Click="BtnSave_Click"-->
<DataGrid x:Name="dgEmployee" HorizontalAlignment="Left" Height="410" Margin="259,0,0,0"
xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
CanUserAddRows="True"
ItemsSource="{Binding EMPLOYEEs}"
SelectedItem="{Binding EMPLOYEE}"
AutoGenerateColumns="False"
VerticalAlignment="Top" Width="525">
<DataGrid.Columns>
<DataGridTextColumn Header="EMPLOYEEID" Binding="{Binding Path=EMPLOYEEID}"/>
<DataGridTextColumn Header="NAME" Binding="{Binding Path=NAME}"/>
<DataGridTextColumn Header="POSITION" Binding="{Binding Path=POSITION}"/>
<DataGridTextColumn Header="AGE" Binding="{Binding Path=AGE}"/>
<DataGridTextColumn Header="SALARY" Binding="{Binding Path=SALARY}"/>
<DataGridTemplateColumn Header="Edit Action">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding EditCommand }">
Edit
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Delete Action">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding DeleteCommand }">
Delete
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="btnLoad" Command="{Binding LoadCommand }" Content="Load" HorizontalAlignment="Left" Margin="28,189,0,0" VerticalAlignment="Top" Width="96"/>
<!--Click="BtnLoad_Click"/>-->
<!--<Label x:Name="lblMessage" Content="" HorizontalAlignment="Left" Margin="114,158,0,0" VerticalAlignment="Top"/>-->
<Label x:Name="lblPOSITION" Content="POSITION" HorizontalAlignment="Left" Margin="28,72,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblAGE" Content="AGE" HorizontalAlignment="Left" Margin="28,103,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblSALARY" Content="SALARY" HorizontalAlignment="Left" Margin="28,140,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtPOSITION" Text="{Binding EMPLOYEE.POSITION}" HorizontalAlignment="Left" Height="23" Margin="134,76,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txtAGE" Text="{Binding EMPLOYEE.AGE}" HorizontalAlignment="Left" Height="23" Margin="134,107,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txtSALARY" Text="{Binding EMPLOYEE.SALARY}" HorizontalAlignment="Left" Height="23" Margin="134,143,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
</Grid>
ViewModel
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using WpfAppCallingAPI.Command;
using WpfAppCallingAPI.Models;
using WpfAppCallingAPI.View;
using System.Configuration;
namespace WpfAppCallingAPI.ViewModel
{
public class EmployeeViewModel : INotifyPropertyChanged
{
private EMPLOYEE employee;
public EMPLOYEE EMPLOYEE
{
get { return employee; }
set { employee = value; NotifyPropertyChanged("EMPLOYEE"); }
}
private void NotifyPropertyChanged(string v)
{
PropertyChangedEventHandler ph = PropertyChanged;
if (ph != null)
ph(this, new PropertyChangedEventArgs(v));
}
private ObservableCollection<EMPLOYEE> Employees;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<EMPLOYEE> EMPLOYEEs
{
get
{
return Employees;
}
set
{
Employees = value;
NotifyPropertyChanged("EMPLOYEEs");
}
}
HttpClient client = new HttpClient();
public EmployeeViewModel()
{
client.BaseAddress = new Uri("http://localhost:64028/api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
LoadCommand = new RelayCommand(o => LoadButtonClick("LoadButton"));
SaveCommand = new RelayCommand(o => SaveButtonClick("SaveButton"));
}
public ICommand LoadCommand { get; set; }
public ICommand SaveCommand { get; set; }
private void LoadButtonClick(object sender)
{
//MessageBox.Show(sender.ToString());
this.GetEmployees();
}
private async void GetEmployees()
{
var response = await client.GetStringAsync("employee");
EMPLOYEEs = new ObservableCollection<EMPLOYEE>(JsonConvert.DeserializeObject<List<EMPLOYEE>>(response));
}
private async void SaveEmployees(EMPLOYEE employee)
{
await client.PostAsJsonAsync("employee/", employee);
}
private void SaveButtonClick(object sender)
{
var employee = new EMPLOYEE()
{
EMPLOYEEID = Convert.ToDecimal(txtEMPLOYEEID.Text),
NAME = txtNAME.Text,
POSITION = txtPOSITION.Text,
AGE = Convert.ToDecimal(txtAGE.Text),
SALARY = Convert.ToDecimal(txtSALARY.Text)
};
this.SaveEmployees(employee);
//lblMessage.Content = "Saved";
txtEMPLOYEEID.Text = 0.ToString();
txtNAME.Text = "";
txtPOSITION.Text = "";
txtAGE.Text = 0.ToString();
txtSALARY.Text = 0.ToString();
}
}
Model
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfAppCallingAPI.Models
{
public partial class EMPLOYEE : INotifyPropertyChanged
{
private decimal eMPLOYEEID;
public decimal EMPLOYEEID
{
get { return eMPLOYEEID; }
set { eMPLOYEEID = value; OnPropertyChanged(EMPLOYEEID.ToString()); }
}
//private void OnPropertyChanged(decimal eMPLOYEEID)
//{
// throw new NotImplementedException();
//}
//public decimal EMPLOYEEID { get; set; }
private string nAME;
public string NAME
{
get { return nAME; }
set { nAME = value; OnPropertyChanged(NAME); }
}
//public string NAME { get; set; }
private string pOSITION;
public string POSITION
{
get { return pOSITION; }
set { pOSITION = value; OnPropertyChanged(POSITION); }
}
//public string POSITION { get; set; }
//public Nullable<decimal> AGE { get; set; }
private Nullable<decimal> aGE;
public Nullable<decimal> AGE
{
get { return aGE; }
set { aGE = value; OnPropertyChanged(AGE.ToString()); }
}
//public Nullable<decimal> SALARY { get; set; }
private Nullable<decimal> sALARY;
public Nullable<decimal> SALARY
{
get { return sALARY; }
set { sALARY = value; OnPropertyChanged(SALARY.ToString()); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string p)
{
PropertyChangedEventHandler ph = PropertyChanged;
if (ph != null)
ph(this, new PropertyChangedEventArgs(p));
}
}
}
RelayCommand
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfAppCallingAPI.Command
{
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null) throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested = value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter ?? "<N/A>");
}
}
}
CodePudding user response:
On Client Side
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:64028/api/");
StringContent content = new(JsonSerializer.Serialize(employeeToSave),Encoding.UTF8, "application/json");
var response = await client.PostAsync($"yourApiEmployeeController", content);
if (response.StatusCode == HttpStatusCode.OK)
{
Success;
}
else
{
Failed;
}
ON Api Side Insert Action
[HttpPost]
public async Task<ActionResult<Employee>> Insert([FromBody] JsonElement jsonData)
{
try
{
var employeeToSave = jsonData.Deserialize<Employee>();
await //write your save method
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
}
}
CodePudding user response:
may be CORS you can see the head with postman(it can intercept the request)