独自にAPIを増やしてデスクトップアプリでプリザンターのすべてを見てみた!
IISの石崎です。
以前に「プリザンターのAPI連携をデスクトップアプリで使ってみた!」という記事を書きました。
今回は、独自にAPIを増やして内部データを含むすべてのテーブルを表示するデスクトップアプリをC#で書いてみます。
独自にAPIを増やすことでできること
独自にAPIを増やすことで、そもそもWebやデスクトップなどのアプリとして難しい事を除いて概ね何でもできます。場合によってはAPIではなく独自に画面を増やすことも可能です。
例えば次のユースケースなども実現できます。
- テーブルの設定をExcelのような見た目で一覧表示したい
- エディタの設定をExcelのような見た目で一覧表示したい
- アクセス制御の設定をExcelのような見た目で一覧表示したい
- データの登録件数や状況のサマリーを一覧表示したい
- プリザンターの使われ方を分析したい
表示するより手間はかかりますが、データの追加更新を行うAPIも増やすことが可能です。そうすると次の様なユースケースにも対応可能です。
- データを一覧形式で登録・編集したい
- テータを独自の画面で登録・編集したい
- テーブルの設定を独自の画面で編集したい
- 独自のフォーマットでデータのファイル出力・取込機能をしたい
デスクトップアプリ
今回作ってみたデスクトップアプリの見た目です。独自に増やしたAPIで取ってきた情報を一覧表示しています。
コード
コード全体はこのようになっています。jsonを扱うためにNuGetでJson.NETをインストールしています。
<Window x:Class="WpfApp1.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:WpfApp1" mc:Ignorable="d" Title="AllAboutPleassanter" Height="1800" Width="1000" Icon="icon.png"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Label Content="すべてのテーブルのデータを表示するデスクトップアプリ" Margin="5,0" Background="MediumBlue" Foreground="White" FontWeight="ExtraBold"/> <Button Content=" すべてを取得 " Margin="5,0" HorizontalAlignment="Right" Click="Button_Click"/> <ScrollViewer Grid.Row="1"> <Grid Margin="5"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Binaries: " Grid.Row="0"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Demos: " Grid.Row="1"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Depts: " Grid.Row="2"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="ExportSettings: " Grid.Row="3"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="GroupMembers: " Grid.Row="4"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Groups: " Grid.Row="5"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Healths: " Grid.Row="6"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Issues: " Grid.Row="7"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Items: " Grid.Row="8"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Links: " Grid.Row="9"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="LoginKeys: " Grid.Row="10"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="MailAddresses: " Grid.Row="11"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Orders: " Grid.Row="12"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="OutgoingMails: " Grid.Row="13"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Permissions: " Grid.Row="14"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="ReminderSchedules: " Grid.Row="15"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Results: " Grid.Row="16"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="SearchIndexes: " Grid.Row="17"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Sites: " Grid.Row="18"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Statuses: " Grid.Row="19"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="SysLogs: " Grid.Row="20"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Tenants: " Grid.Row="21"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Users: " Grid.Row="22"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Text="Wikis: " Grid.Row="23"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridBinaries" Grid.Row="0"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridDemos" Grid.Row="1"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridDepts" Grid.Row="2"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridExportSettings" Grid.Row="3"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridGroupMembers" Grid.Row="4"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridGroups" Grid.Row="5"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridHealths" Grid.Row="6"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridIssues" Grid.Row="7"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridItems" Grid.Row="8"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridLinks" Grid.Row="9"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridLoginKeys" Grid.Row="10"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridMailAddresses" Grid.Row="11"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridOrders" Grid.Row="12"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridOutgoingMails" Grid.Row="13"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridPermissions" Grid.Row="14"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridReminderSchedules" Grid.Row="15"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridResults" Grid.Row="16"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridSearchIndexes" Grid.Row="17"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridSites" Grid.Row="18"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridStatuses" Grid.Row="19"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridSysLogs" Grid.Row="20"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridTenants" Grid.Row="21"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridUsers" Grid.Row="22"/> <DataGrid ItemsSource="{Binding}" Grid.Column="1" IsReadOnly="True" x:Name="dataGridWikis" Grid.Row="23"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="0"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="1"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="2"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="3"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="4"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="5"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="6"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="7"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="8"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="9"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="10"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="11"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="12"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="13"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="14"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="15"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="16"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="17"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="18"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="19"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="20"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="21"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="22"/> <Grid Height="1" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="23"/> <Grid Width="1" Background="LightBlue" HorizontalAlignment="Left" VerticalAlignment="Stretch" Grid.Column="0" Grid.RowSpan="24"/> </Grid> </ScrollViewer> </Grid> </Window>
using Newtonsoft.Json; using System.Collections.Generic; using System.Data; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Windows; namespace WpfApp1 { /// <summary> /// View クラス /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } /// <summary> /// すべてを取得ボタンの処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void Button_Click(object sender, RoutedEventArgs e) { // Apiキー、HttpClient の準備 var apiKey = "取得したAPIキー"; var httpClient = new HttpClient(); // 取得条件のセット var requestData = new ApiRequest(); // API 呼び出し テーブルの値を取得、DataGridへ表示 var apiClient = new ApiClient(); dataGridBinaries.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyBinaries", requestData); dataGridDemos.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyDemos", requestData); dataGridDepts.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyDepts", requestData); dataGridExportSettings.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyExportSettings", requestData); dataGridGroupMembers.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyGroupMembers", requestData); dataGridGroups.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyGroups", requestData); dataGridHealths.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyHealths", requestData); dataGridIssues.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyIssues", requestData); dataGridItems.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyItems", requestData); dataGridLinks.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyLinks", requestData); dataGridLoginKeys.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyLoginKeys", requestData); dataGridMailAddresses.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyMailAddresses", requestData); dataGridOrders.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyOrders", requestData); dataGridOutgoingMails.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyOutgoingMails", requestData); dataGridPermissions.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyPermissions", requestData); dataGridReminderSchedules.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyReminderSchedules", requestData); dataGridResults.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyResults", requestData); dataGridSearchIndexes.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MySearchIndexes", requestData); dataGridSites.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MySites", requestData); dataGridStatuses.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyStatuses", requestData); dataGridSysLogs.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MySysLogs", requestData); dataGridTenants.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyTenants", requestData); dataGridUsers.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyUsers", requestData); dataGridWikis.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyWikis", requestData); } } /// <summary> /// API クライアントクラス /// </summary> public class ApiClient { public async Task<DataTable> GetDataAsync(HttpClient httpClient, string apiKey, string baseUrl, string apiName, string apiMethod, ApiRequest requestData) { requestData.ApiKey = apiKey; var json = JsonConvert.SerializeObject(requestData); var content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded"); var response = await httpClient.PostAsync($"{baseUrl}/{apiName}/{apiMethod}", content); var responseContentString = await response?.Content?.ReadAsStringAsync(); var responseContent = JsonConvert.DeserializeObject<DataTable>(responseContentString); return responseContent; } public async Task<DataTable> GetDataAsync(HttpClient httpClient, string apiKey, string apiName, ApiRequest requestData) => await GetDataAsync(httpClient, apiKey, "http://localhost:1759/", apiName, "get", requestData); } /// <summary> /// API リクエストデータモデル /// </summary> public class ApiRequest { public string ApiKey { get; set; } public long Offset { get; set; } public View View { get; } = new View(); } /// <summary> /// API リクエストデータモデルに保持されるデータモデル /// </summary> public class View { public Dictionary<string, string> ColumnFilterHash { get; } = new Dictionary<string, string>(); } }
軽く解説
・メインの処理
メインの処理はMainWindowのButton_Clickメソッドです。取得条件(変数名: requestData)を構築して、API呼び出し処理(クラス名: ApiClient)でAPIを呼び出しています。取得結果はDataGridへセットし画面表示しています。サンプルコードとして分かりやすくするために、24のテーブルのデータを表示する24回のAPI呼び出しとDataGridへのセットが書かれているためコードが長くなっていますが、やっていることは単純です。
// Apiキー、HttpClient の準備 var apiKey = "取得したAPIキー"; var httpClient = new HttpClient(); // 取得条件のセット var requestData = new ApiRequest(); // API 呼び出し テーブルの値を取得、DataGridへ表示 var apiClient = new ApiClient(); dataGridBinaries.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyBinaries", equestData); dataGridDemos.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyDemos", equestData); dataGridDepts.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyDepts", equestData); dataGridExportSettings.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyExportSettings", requestData); dataGridGroupMembers.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyGroupMembers", requestData); dataGridGroups.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyGroups", equestData); dataGridHealths.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyHealths", equestData); dataGridIssues.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyIssues", equestData); dataGridItems.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyItems", equestData); dataGridLinks.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyLinks", equestData); dataGridLoginKeys.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyLoginKeys", requestData); dataGridMailAddresses.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyMailAddresses", requestData); dataGridOrders.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyOrders", equestData); dataGridOutgoingMails.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyOutgoingMails", requestData); dataGridPermissions.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyPermissions", requestData); dataGridReminderSchedules.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MyReminderSchedules", requestData); dataGridResults.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyResults", equestData); dataGridSearchIndexes.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, MySearchIndexes", requestData); dataGridSites.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MySites", equestData); dataGridStatuses.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyStatuses", equestData); dataGridSysLogs.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MySysLogs", equestData); dataGridTenants.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyTenants", equestData); dataGridUsers.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyUsers", equestData); dataGridWikis.DataContext = await apiClient.GetDataAsync(httpClient, apiKey, "MyWikis", equestData);
・API呼び出し処理
APIを呼ぶ手続きをApiClientクラスにまとめています。こちらもサンプルコードとして分かりやすく書いているため、実際にコードを書く際には、もう少し手を入れたコードにした方が良いかもしれません。
public class ApiClient { public async Task<DataTable> GetDataAsync(HttpClient httpClient, string apiKey, string baseUrl, string apiName, string apiMethod, ApiRequest requestData) { requestData.ApiKey = apiKey; var json = JsonConvert.SerializeObject(requestData); var content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded"); var response = await httpClient.PostAsync($"{baseUrl}/{apiName}/{apiMethod}", content); var responseContentString = await response?.Content?.ReadAsStringAsync(); var responseContent = JsonConvert.DeserializeObject<DataTable>(responseContentString); return responseContent; } public async Task<DataTable> GetDataAsync(HttpClient httpClient, string apiKey, string apiName, ApiRequest requestData) => await GetDataAsync(httpClient, apiKey, "http://localhost:1759/", apiName, "get", requestData); }
・POCO
残りのクラスは、APIで送信するデータを持つPOCOです。今回は、受信データの種類が多いので受信用のデータモデルは作成せず、DataTableクラスを使用しています。DataTableクラスは積極的に使うクラスではないですが、検証コードなどでは意外と便利に使えます。
public class ApiRequest { public string ApiKey { get; set; } public long Offset { get; set; } public View View { get; } = new View(); } public class View { public Dictionary<string, string> ColumnFilterHash { get; } = new Dictionary<string, string>(); }
上記コードで呼び出しているAPIはIIS固有の技術で独自に増やしています。この固有技術によりプリザンター自体に手を加えることなくAPIを追加することが可能です。
プリザンター自体に手を入れるカスタマイズ手法だとアップデートに度に多くの手間が必要になりますが、IISの技法でなら手間はほとんどかかりません。
今後の野望
今回は、ただデータを一通り取得して表示しただけですが、今後は
- テーブルの設定をExcelのような見た目で一覧表示したい
- エディタの設定をExcelのような見た目で一覧表示したい
- アクセス制御の設定をExcelのような見た目で一覧表示したい
- データの登録件数や状況のサマリーを一覧表示したい
- プリザンターの使われ方を分析したい
- データを一覧形式で登録・編集したい
- テータを独自の画面で登録・編集したい
- テーブルの設定を独自の画面で編集したい
- 独自のフォーマットでデータのファイル出力・取込機能をしたい
といった夢をかなえるAPIを作って、皆様のお役に立てる製品を開発して行きます。個別のカスタマイズのご相談も歓迎です。
最後に
C#によるデスクトップアプリ開発はIISが最も得意とする領域です。今後もプリザンターとデスクトップアプリの連携の研究を進めて行くつもりです。デスクトップアプリとの連携に関心のある方、よかったらブログ上部の「+読者になる」をクリックをお願いします!