Home > Software design >  Insert, Update & Delete in WPF MVVM using Web API
Insert, Update & Delete in WPF MVVM using Web API

Time:03-01

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)

  • Related