This commit is contained in:
dev01 2023-01-13 18:45:44 +08:00
commit 6d57a2b200
9 changed files with 309 additions and 94 deletions

View File

@ -9,6 +9,8 @@ using Backend.Services;
using Backend.Services.Implement; using Backend.Services.Implement;
using Repository.Models; using Repository.Models;
using System.Linq; using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using NPOI.SS.Formula.Functions;
namespace Backend.Controllers namespace Backend.Controllers
{ {
@ -46,7 +48,7 @@ namespace Backend.Controllers
string top100 = "";//" top 100 "; string top100 = "";//" top 100 ";
webRequestService svc = new webRequestService(); webRequestService svc = new webRequestService();
string bql = url_slot + "bql:select " + top100 + " * from control:ControlPoint "; string bql = url_slot + "bql:select " + top100 + " * from baja:Folder ";
//ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql); //ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql);
//ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql); //ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql);
ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Program/ObixQuery/query/", bql);//三菱 ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Program/ObixQuery/query/", bql);//三菱
@ -79,9 +81,7 @@ namespace Backend.Controllers
{ {
var building = ds.FirstOrDefault().building; var building = ds.FirstOrDefault().building;
await niagaraDataSynchronizeRepository.InsertNiagaraTagList(ds, building); await niagaraDataSynchronizeRepository.InsertNiagaraTagList(ds, building);
await niagaraDataSynchronizeRepository.InsertItemFromNiagara(ds, building);
await niagaraDataSynchronizeRepository.DeviceComparison(); await niagaraDataSynchronizeRepository.DeviceComparison();
await niagaraDataSynchronizeRepository.DeviceItemComparison();
await niagaraDataSynchronizeRepository.InsertBuildingMenu(); await niagaraDataSynchronizeRepository.InsertBuildingMenu();
await niagaraDataSynchronizeRepository.InsertSubSystemFloor(); await niagaraDataSynchronizeRepository.InsertSubSystemFloor();
result = true; result = true;
@ -98,5 +98,65 @@ namespace Backend.Controllers
return apiResult; return apiResult;
} }
/// <summary>
/// N4匯入列表(device_item)
/// </summary>
/// <returns></returns>
[HttpPost]
public Task<ApiResult<List<ImpNiaItem>>> RawDataDevItemList()
{
ApiResult<List<ImpNiaItem>> apiResult = new ApiResult<List<ImpNiaItem>>();
try
{
List<ImpNiaItem> ds;
string url_slot = "slot:/TPE/B1|";//三菱
//string url_slot = "slot:/NTPC/B1|";//wsp
webRequestService svc = new webRequestService();
ds = svc.obixHisQuery("http://192.168.0.136:8080/obix/config/Program/ObixQuery/query/", "http://192.168.0.136:8080/obix/histories", url_slot);//三菱
//ds = svc.obixHisQuery("http://192.168.0.136:8081/obix/config/Program/ObixQuery/query/", "http://192.168.0.136:8081/obix/histories", url_slot);//wsp
apiResult.Code = "0000";
apiResult.Data = ds;
}
catch (Exception exception)
{
apiResult.Code = "9999";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
//return apiResult;
return Task.FromResult(apiResult);
}
/// <summary>
/// 比對N4與資料表有差異在同步至資料表中(device_item)
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> DevIteComData([FromBody] List<ImpNiaItem> ds)
{
bool result = false;
ApiResult<bool> apiResult = new ApiResult<bool>();
try
{
var building = ds.FirstOrDefault().device_building_tag;
await niagaraDataSynchronizeRepository.InsertItemFromNiagara(ds, building);
await niagaraDataSynchronizeRepository.DeviceItemComparison();
result = true;
apiResult.Code = "0000";
apiResult.Data = result;
}
catch (Exception exception)
{
apiResult.Code = "9999";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return apiResult;
}
} }
} }

View File

@ -12,6 +12,9 @@ using System.Xml.Linq;
using Repository.BackendRepository.Implement; using Repository.BackendRepository.Implement;
using Repository.BackendRepository; using Repository.BackendRepository;
using Ubiety.Dns.Core; using Ubiety.Dns.Core;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace Backend.Services.Implement namespace Backend.Services.Implement
{ {
@ -55,40 +58,150 @@ namespace Backend.Services.Implement
row.value = item.Val; row.value = item.Val;
string[] s1 = item.Val.Split(','); string[] s1 = item.Val.Split(',');
string[] s2 = s1[0].Split('/'); string[] s2 = s1[0].Remove(s1[0].Length - 1, 1).Remove(0, 1).Split('/');
string displayName = s1[1].Split('=')[1];
row.tag_name = ""; row.tag_name = "";
for (int i = 0; i < s2.Length; i++) if (s2.Length == 8)
{ {
if (i == s2.Length - 2) for (int i = 0; i < s2.Length; i++)
{ {
row.point_name = s2[i]; if (i == s2.Length - 2)
}
else if (i == 1)
{
row.tag_name += s2[i];
}
else if (i > 1 && i < s2.Length - 2)
{
row.tag_name += "_" + s2[i];
}
}
/*foreach (var ss in s2)
{
if (ss.Contains('_'))
{
string[] s3 = ss.Split('_');
if (s3.Count() > 3)
{ {
row.tag_name = ss; row.point_name = s2[i];
row.point_name = s2[s2.Length - 2]; }
break; else if (i == 1)
{
row.tag_name += s2[i];
}
else if (i > 1 && i < s2.Length - 2)
{
row.tag_name += "_" + s2[i];
} }
} }
}*/
result.Add(row);
row.displayName = displayName;
/*foreach (var ss in s2)
{
if (ss.Contains('_'))
{
string[] s3 = ss.Split('_');
if (s3.Count() > 3)
{
row.tag_name = ss;
row.point_name = s2[s2.Length - 2];
break;
}
}
}*/
result.Add(row);
}
} }
return result;
}
public List<ImpNiaItem> obixHisQuery(string bqlUrlString, string urlString, string slot)
{
String username = "obixUser";
String password = "Admin123456";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
#region get control point data
List<control_point> conPoint = new List<control_point>();
String cp_API_Url = bqlUrlString;
HttpWebRequest cp_Postrequest = (HttpWebRequest)WebRequest.Create(cp_API_Url);
cp_Postrequest.Method = "POST";
cp_Postrequest.Headers.Add("Authorization", "Basic " + encoded);
cp_Postrequest.PreAuthenticate = true;
using (var streamWriter = new StreamWriter(cp_Postrequest.GetRequestStream()))
{
string json = "<str val='" + slot + "bql: select * from control:ControlPoint'/>";
streamWriter.Write(json);
}
HttpWebResponse cp_response = (HttpWebResponse)cp_Postrequest.GetResponse();
var cp_responseString = new StreamReader(cp_response.GetResponseStream()).ReadToEnd();
XmlDocument cp_xmlDoc = new XmlDocument();
cp_xmlDoc.LoadXml(cp_responseString);
string cp_jsonText = JsonConvert.SerializeXmlNode(cp_xmlDoc);
var cp_data = Welcome.FromJson(cp_jsonText);
foreach (var item in cp_data.Obj.Str)
{
control_point row = new control_point();
string[] s1 = item.Val.Split(',');
string[] s2 = s1[0].Split('/');
var displayName = s1[1].Split('=')[1];
row.name = s1[0].Replace('/', '_').Remove(s1[0].Length - 1, 1).Remove(0, 1);
row.displayName = displayName;
conPoint.Add(row);
}
#endregion
#region main program
List<ImpNiaItem> result = new List<ImpNiaItem>();
String API_Url = urlString;
HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(API_Url);
Postrequest.Method = "GET";
Postrequest.Headers.Add("Authorization", "Basic " + encoded);
Postrequest.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(responseString);
string jsonText = JsonConvert.SerializeXmlNode(xmlDoc);
var data = Welcome.FromJson(jsonText);
foreach (var item in data.Obj.Ref)
{
String API_Url2 = urlString + "/" + item.Name;
HttpWebRequest Postrequest2 = (HttpWebRequest)WebRequest.Create(API_Url2);
Postrequest2.Method = "GET";
Postrequest2.Headers.Add("Authorization", "Basic " + encoded);
Postrequest2.PreAuthenticate = true;
HttpWebResponse response2 = (HttpWebResponse)Postrequest2.GetResponse();
var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();
XmlDocument xmlDoc2 = new XmlDocument();
xmlDoc2.LoadXml(responseString2);
string jsonText2 = JsonConvert.SerializeXmlNode(xmlDoc2);
var data2 = Welcome.FromJson(jsonText2);
foreach (var item2 in data2.Obj.Ref)
{
if (item2.Name.Split('_').Length == 9)
{
ImpNiaItem row = new ImpNiaItem();
row.device_area_tag = item2.Name.Split('_')[0];
row.device_building_tag = item2.Name.Split('_')[1];
row.device_system_tag = item2.Name.Split('_')[2];
row.device_name_tag = item2.Name.Split('_')[3];
row.device_point_name = item2.Name.Split('_')[8];
row.parent_path = item.Name;
row.full_name = conPoint.Where(x => x.name == item2.Name).Select(x => x.displayName).FirstOrDefault();
result.Add(row);
}
}
}
#endregion
return result; return result;
} }

View File

@ -163,9 +163,10 @@
document.getElementById('loadDataText').innerText = "比對資料出錯了!"; document.getElementById('loadDataText').innerText = "比對資料出錯了!";
return; return;
} }
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); SyncDevItem();
var dateTime = date + ' ' + time; //var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
document.getElementById('loadDataText').innerText = "比對完成 \n" + dateTime; //var dateTime = date + ' ' + time;
//document.getElementById('loadDataText').innerText = "比對完成 \n" + dateTime;
}, },
}); });
} }
@ -174,5 +175,48 @@
} }
} }
function SyncDevItem()
{
//比對資料有差異的話再同步到device等資料表
var url_synchronize_data = "/NiagaraDataSynchronize/RawDataDevItemList/";
var url_synchronize_data_device_item = "/NiagaraDataSynchronize/DevIteComData/";
$.ajax({
method: "POST",
url: url_synchronize_data,
success: function (rel) {
if (rel.code != "0000") {
toast_error(rel.msg);
document.getElementById('loadDataText').innerText = "比對資料出錯了!";
return;
}
$.ajax({
method: "POST",
url: url_synchronize_data_device_item,
data: JSON.stringify(rel.data),
cache: false,
async: false,
contentType: "application/json; charset=UTF-8",
dataType: 'json',
success: function (rel) {
if (rel.code != "0000") {
toast_error(rel.msg);
document.getElementById('loadDataText').innerText = "比對資料出錯了!";
return;
}
console.log(rel);
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime = date + ' ' + time;
document.getElementById('loadDataText').innerText = "比對完成 \n" + dateTime;
},
})
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime = date + ' ' + time;
document.getElementById('loadDataText').innerText = "比對完成 \n" + dateTime;
},
});
}
</script> </script>
} }

View File

@ -249,6 +249,7 @@
strHtml += `<button onClick="setValue(null, null, '${val.points}', this)" type="button" class="btn btn-info waves-effect waves-themed">${val.full_name} ${val.points}</button>`; strHtml += `<button onClick="setValue(null, null, '${val.points}', this)" type="button" class="btn btn-info waves-effect waves-themed">${val.full_name} ${val.points}</button>`;
pageAct.deviceItem = val.points; pageAct.deviceItem = val.points;
pageAct.devicePoiName = val.full_name + ' ' + val.points; pageAct.devicePoiName = val.full_name + ' ' + val.points;
pageAct.deviceComName = val.parent_path;
getData(); getData();
} else { } else {
strHtml += `<button onClick="setValue(null, null, '${val.points}', this)" type="button" class="btn btn-secondary waves-effect waves-themed">${val.full_name} ${val.points}</button>`; strHtml += `<button onClick="setValue(null, null, '${val.points}', this)" type="button" class="btn btn-secondary waves-effect waves-themed">${val.full_name} ${val.points}</button>`;
@ -269,7 +270,7 @@
new Date(start).getTime(), new Date(start).getTime(),
new Date(end).getTime(), new Date(end).getTime(),
pageAct.deviceName, pageAct.deviceName,
"Mitsubishi_JACE8000", pageAct.deviceComName,
callBackFromHistory); callBackFromHistory);
} }

View File

@ -214,6 +214,7 @@ namespace FrontendWebApi.Models
public string full_name { get; set; } public string full_name { get; set; }
public string points { get; set; } public string points { get; set; }
public string unit { get; set; } public string unit { get; set; }
public string parent_path { get; set; }
} }
public class DeviceList public class DeviceList

View File

@ -73,7 +73,7 @@ namespace Repository.BackendRepository.Implement
if (arrTag.Length == 8) if (arrTag.Length == 8)
{ {
sb.Append($@" insert import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag, sb.Append($@" insert import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag,
device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, atDateTime) values('" + device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_full_name, atDateTime) values('" +
row.tag_name + "', '" + row.tag_name + "', '" +
arrTag[0] + "', '" + arrTag[0] + "', '" +
arrTag[1] + "', '" + arrTag[1] + "', '" +
@ -83,6 +83,7 @@ namespace Repository.BackendRepository.Implement
arrTag[5] + "', '" + arrTag[5] + "', '" +
arrTag[6] + "', '" + arrTag[6] + "', '" +
arrTag[7] + "', " + arrTag[7] + "', " +
row.displayName + "', '" +
"now());"); "now());");
} }
} }
@ -110,7 +111,7 @@ namespace Repository.BackendRepository.Implement
/// <param name="ds"></param> /// <param name="ds"></param>
/// <param name="building"></param> /// <param name="building"></param>
/// <returns></returns> /// <returns></returns>
public async Task InsertItemFromNiagara(List<Device_value> ds, string building) public async Task InsertItemFromNiagara(List<ImpNiaItem> ds, string building)
{ {
using (IDbConnection conn = GetDbConnection()) using (IDbConnection conn = GetDbConnection())
{ {
@ -128,6 +129,8 @@ namespace Repository.BackendRepository.Implement
`device_name_tag` varchar(50) DEFAULT NULL, `device_name_tag` varchar(50) DEFAULT NULL,
`device_point_name` varchar(50) DEFAULT NULL, `device_point_name` varchar(50) DEFAULT NULL,
`check_status` varchar(50) DEFAULT NULL, `check_status` varchar(50) DEFAULT NULL,
`parent_path` varchar(50) DEFAULT NULL,
`full_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
await conn.ExecuteAsync(sql); await conn.ExecuteAsync(sql);
@ -135,62 +138,22 @@ namespace Repository.BackendRepository.Implement
await conn.ExecuteAsync(sql); await conn.ExecuteAsync(sql);
#endregion #endregion
List<Device_item8> dt_item = new List<Device_item8>(); StringBuilder sb = new StringBuilder();
#region import_niagara_item資料表
foreach (var row in ds) foreach (var row in ds)
{ {
if (string.IsNullOrEmpty(row.tag_name)) continue; sb.Append($@" insert import_niagara_item(device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_point_name, parent_path, full_name)
string[] arrTag = row.tag_name.Split('_'); values('"+
row.device_area_tag + "', '" +
#region for item row.device_building_tag + "', '" +
if (arrTag.Length == 8) row.device_system_tag + "', '" +
{ row.device_name_tag + "', '" +
Device_item8 row_item = new Device_item8(); row.device_point_name + "', '" +
row_item.tag_name = row.tag_name; row.parent_path + "', '" +
row_item.device_area_tag = arrTag[0]; row.full_name + "'" +
row_item.device_building_tag = arrTag[1]; ");");
row_item.device_system_tag = arrTag[2];
row_item.device_name_tag = arrTag[3];
row_item.device_floor_tag = arrTag[4];
row_item.device_master_tag = arrTag[5];
row_item.device_last_name_tag = arrTag[6];
row_item.device_serial_tag = arrTag[7];
row_item.point_name = row.point_name;
dt_item.Add(row_item);
}
#endregion
} }
#region N4資料groupBy後放入import_niagara_item資料表
var ds2_item = dt_item.GroupBy(x => new
{
device_area_tag2 = x.device_area_tag,
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag,
point_name2 = x.point_name
}).Select(x => new Device_item8
{
device_area_tag = x.Key.device_area_tag2,
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2,
point_name = x.Key.point_name2
});
StringBuilder sb = new StringBuilder();
foreach (var row2 in ds2_item)
{
sb.Append($@" insert import_niagara_item(device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_point_name)
values('" +
row2.device_area_tag + "', '" +
row2.device_building_tag + "', '" +
row2.device_system_tag + "', '" +
row2.device_name_tag + "', '" +
row2.point_name + "'" +
");");
}
if (sb.Length > 0) if (sb.Length > 0)
{ {
await conn.ExecuteAsync(sb.ToString()); await conn.ExecuteAsync(sb.ToString());
@ -251,14 +214,14 @@ namespace Repository.BackendRepository.Implement
foreach (var data in result) foreach (var data in result)
{ {
sb.Append($@" insert device(device_guid, deleted, status, priority, is_link, device_area_tag, sb.Append($@" insert device(device_guid, deleted, status, priority, is_link, device_area_tag,
device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_master, device_building_tag, device_system_tag, device_name_tag, full_name, device_floor_tag, device_master,
device_last_name, device_serial_tag, device_number, device_system_category_layer3, created_at, updated_at) device_last_name, device_serial_tag, device_number, device_system_category_layer3, created_at, updated_at)
values(uuid(), 0, 1, 0, 1, '" + values(uuid(), 0, 1, 0, 1, '" +
data.device_area_tag + "', '" + data.device_area_tag + "', '" +
data.device_building_tag + "', '" + data.device_building_tag + "', '" +
data.device_system_tag + "', '" + data.device_system_tag + "', '" +
data.device_name_tag + "', '" + data.device_name_tag + "', '" +
data.device_full_name + "', '" +
data.device_floor_tag + "', '" + data.device_floor_tag + "', '" +
data.device_master_tag + "', '" + data.device_master_tag + "', '" +
data.device_last_name_tag + "', '" + data.device_last_name_tag + "', '" +
@ -351,13 +314,15 @@ namespace Repository.BackendRepository.Implement
isBool = 1; isBool = 1;
} }
sb.Append($@"insert device_item(deleted, points, is_show, is_show_riserDiagram, is_controll, is_bool, is_link, is_show_history, sb.Append($@"insert device_item(deleted, points, is_show, is_show_riserDiagram, is_controll, is_bool, is_link, is_show_history,
device_system_tag, device_name_tag, created_at, updated_at) device_system_tag, device_name_tag, full_name, parent_path, created_at, updated_at)
VALUES (0, '" + VALUES (0, '" +
data.device_point_name + "', 1, 0, " + data.device_point_name + "', 1, 0, " +
isControll + "," + isControll + "," +
isBool + ", 1, 1, '" + isBool + ", 1, 1, '" +
data.device_system_tag + "', '" + data.device_system_tag + "', '" +
data.device_name_tag + "', " + data.device_name_tag + "', " +
data.full_name + "', " +
data.parent_path + "', " +
"now(), now());"); "now(), now());");
} }
if (sb.Length > 0) if (sb.Length > 0)

View File

@ -19,7 +19,7 @@ namespace Repository.BackendRepository.Interface
/// <param name="ds"></param> /// <param name="ds"></param>
/// <param name="building"></param> /// <param name="building"></param>
/// <returns></returns> /// <returns></returns>
Task InsertItemFromNiagara(List<Device_value> ds, string building); Task InsertItemFromNiagara(List<ImpNiaItem> ds, string building);
/// <summary> /// <summary>
/// 比對 device /// 比對 device
/// </summary> /// </summary>

View File

@ -43,13 +43,11 @@ namespace Repository.Models
/// </summary> /// </summary>
public class Device_value public class Device_value
{ {
public string name { get; set; }
public string value { get; set; } public string value { get; set; }
public string tag_name { get; set; } public string tag_name { get; set; }
public string point_name { get; set; } public string point_name { get; set; }
public string building { get; set; } public string building { get; set; }
public string DisplayName { get; set; } public string displayName { get; set; }
public string FullName { get; set; }
} }
public class Device_item8 public class Device_item8
@ -83,6 +81,7 @@ namespace Repository.Models
public string device_master_tag { get; set; } public string device_master_tag { get; set; }
public string device_last_name_tag { get; set; } public string device_last_name_tag { get; set; }
public string device_serial_tag { get; set; } public string device_serial_tag { get; set; }
public string device_full_name { get; set; }
public string atDateTime { get; set; } public string atDateTime { get; set; }
public int is_used { get; set; } public int is_used { get; set; }
} }
@ -94,6 +93,8 @@ namespace Repository.Models
public string device_system_tag { get; set; } public string device_system_tag { get; set; }
public string device_name_tag { get; set; } public string device_name_tag { get; set; }
public string device_point_name { get; set; } public string device_point_name { get; set; }
public string full_name { get; set; }
public string parent_path { get; set; }
} }
public class building_menu public class building_menu
@ -107,4 +108,22 @@ namespace Repository.Models
{ {
public string device_kind_guid { get; set; } public string device_kind_guid { get; set; }
} }
public class ImpNiaItem
{
public string device_area_tag { get; set; }
public string device_building_tag { get; set; }
public string device_system_tag { get; set; }
public string device_name_tag { get; set; }
public string device_point_name { get; set; }
public string parent_path { get; set; }
public string check_status { get; set; }
public string full_name { get; set; }
}
public class control_point
{
public string name { get; set; }
public string displayName { get; set; }
}
} }

View File

@ -33,6 +33,9 @@ namespace Repository.Models
[JsonProperty("str")] [JsonProperty("str")]
public Str[] Str { get; set; } public Str[] Str { get; set; }
[JsonProperty("ref")]
public Str[] Ref { get; set; }
} }
public partial class Str public partial class Str
@ -47,6 +50,15 @@ namespace Repository.Models
public string Href { get; set; } public string Href { get; set; }
} }
public partial class Ref
{
[JsonProperty("@name")]
public string Name { get; set; }
[JsonProperty("@href")]
public string Href { get; set; }
}
public partial class Xml public partial class Xml
{ {
[JsonProperty("@version")] [JsonProperty("@version")]