latest changes
This commit is contained in:
parent
94023034dc
commit
1acf7ad560
@ -60,6 +60,14 @@
|
||||
<None Include="configuration.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Hardware\Common.Hardware.SIRT\Common.Hardware.SIRT.csproj">
|
||||
<Project>{8de8e742-ee0a-4004-aa49-3d08d748e5ac}</Project>
|
||||
<Name>Common.Hardware.SIRT</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Hardware\WaterMeter\eRegister\Common.Hardware.WaterMeter.eRegister\Common.Hardware.WaterMeter.eRegister.csproj">
|
||||
<Project>{4e8bb839-d40a-488c-88ce-f21811f1f476}</Project>
|
||||
<Name>Common.Hardware.WaterMeter.eRegister</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Hardware\WaterMeter\Genesis\GenesisConfig\GenesisConfig.csproj">
|
||||
<Project>{f013a56b-7be6-4852-9cd8-b971cd1add0c}</Project>
|
||||
<Name>GenesisConfig</Name>
|
||||
@ -72,10 +80,6 @@
|
||||
<Project>{f4aaf7e6-7333-4284-b735-e32deb076c64}</Project>
|
||||
<Name>Registers</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LaaPackages\LaaPackages.Features.Cordonel\LaaPackages.Features.Cordonel.csproj">
|
||||
<Project>{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}</Project>
|
||||
<Name>LaaPackages.Features.Cordonel</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Stichproben\Stichproben.csproj">
|
||||
<Project>{F69A79FA-548D-4E21-887E-01FABDAD9E73}</Project>
|
||||
<Name>Stichproben</Name>
|
||||
|
||||
@ -1,10 +1,61 @@
|
||||
namespace CommonConsole
|
||||
{
|
||||
using Common.Hardware.SIRT;
|
||||
using Common.Hardware.SIRT.Parameters;
|
||||
using Common.Hardware.WaterMeter.eRegister.Features;
|
||||
|
||||
using System;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var sirtBroadcaster = new SIRTBroadcaster("COM8");
|
||||
sirtBroadcaster.Logging += Console.WriteLine;
|
||||
sirtBroadcaster.Activated += () =>
|
||||
{
|
||||
sirtBroadcaster.EnqueueTask(new SIRTTask(868)
|
||||
{
|
||||
RequestAddress = 4291709253,
|
||||
P1 = new P811
|
||||
{
|
||||
DelPamSemi = true,
|
||||
},
|
||||
Cmd = SIRTMessage.W_PAM,
|
||||
Data = new OpticalTelegram
|
||||
{
|
||||
Minutes = 0
|
||||
}
|
||||
.Append(new ProvidePin
|
||||
{
|
||||
AuthLevel = AuthLevel.III
|
||||
})
|
||||
.ToByteArray()
|
||||
});
|
||||
sirtBroadcaster.EnqueueTask(new SIRTTask(868)
|
||||
{
|
||||
RequestAddress = 4291762210,
|
||||
P1 = new P811
|
||||
{
|
||||
DelPamSemi = true,
|
||||
},
|
||||
Cmd = SIRTMessage.W_PAM,
|
||||
Data = new OpticalTelegram
|
||||
{
|
||||
Minutes = 0
|
||||
}
|
||||
.Append(new ProvidePin
|
||||
{
|
||||
AuthLevel = AuthLevel.III
|
||||
})
|
||||
.ToByteArray()
|
||||
});
|
||||
};
|
||||
sirtBroadcaster.Open();
|
||||
|
||||
Console.ReadKey();
|
||||
|
||||
sirtBroadcaster.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@
|
||||
LogToFile($"Inserted: {command.ExecuteNonQuery()}");
|
||||
}
|
||||
|
||||
var updated = new HashSet<Int32>();
|
||||
var updated = new Dictionary<int, string>();
|
||||
var countAll = 0;
|
||||
|
||||
using (var command = connection.CreateCommand())
|
||||
@ -127,6 +127,8 @@
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var messageId = reader.GetValue<Int32>(5);
|
||||
|
||||
try
|
||||
{
|
||||
var email = new MailMessage();
|
||||
@ -147,16 +149,16 @@
|
||||
.ToList()
|
||||
.ForEach(email.CC.Add);
|
||||
|
||||
var messageId = reader.GetValue<Int32>(5);
|
||||
|
||||
if (SendEmail(email))
|
||||
{
|
||||
updated.Add(messageId);
|
||||
updated[messageId] = "Sent";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogToFile(e);
|
||||
|
||||
updated[messageId] = e.ToString();
|
||||
}
|
||||
|
||||
countAll++;
|
||||
@ -172,14 +174,22 @@
|
||||
{
|
||||
LogToFile($"updating: {string.Join(", ", updated)}");
|
||||
|
||||
using (var command = connection.CreateCommand())
|
||||
foreach (var kvp in updated)
|
||||
{
|
||||
command.CommandText = $@"
|
||||
UPDATE [Messages]
|
||||
SET [OutDate] = GETDATE()
|
||||
WHERE [Id] IN ({string.Join(", ", updated)})";
|
||||
using (var command = connection.CreateCommand())
|
||||
{
|
||||
command.CommandText = $@"
|
||||
UPDATE [Messages]
|
||||
SET [OutDate] = GETDATE()
|
||||
, [State] = ISNULL([State], '') + ISNULL(@{nameof(kvp.Value)}, '')
|
||||
WHERE [Id] = @{nameof(kvp.Key)}";
|
||||
command.Parameters.Add(new SqlParameter(nameof(kvp.Key), kvp.Key));
|
||||
command.Parameters.Add(new SqlParameter(nameof(kvp.Value), kvp.Value));
|
||||
command.ExecuteNonQuery();
|
||||
command.Parameters.Clear();
|
||||
}
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
updatedCount++;
|
||||
}
|
||||
|
||||
Console.WriteLine($"{updatedCount}/{countAll} email{(updatedCount == 1 ? null : "s")} sent.");
|
||||
|
||||
@ -166,7 +166,7 @@
|
||||
=> this.EOLProgress.Read(pcbId);
|
||||
|
||||
internal virtual CordonelRequirements GetRequirements(int pcbId)
|
||||
=> this.Requirements.FindByPcbId(pcbId.ToString());
|
||||
=> this.Requirements.FindByPcbIdFull(pcbId.ToString(), out _);
|
||||
|
||||
internal virtual IEnumerable<CordonelRegisterHistory> GetLatestRegistersWithValues(int pcbId)
|
||||
=> this.SqlConnection
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
namespace LaaProduction.Data.Cordonel.Interfaces
|
||||
{
|
||||
using System;
|
||||
|
||||
public interface IRepository<T> : IRepositoryEnumerable<T>
|
||||
{
|
||||
T Add(T model);
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
{
|
||||
T FindByPcbId(string pcbid);
|
||||
|
||||
T FindByPcbIdFull(string pcbid, out string error);
|
||||
|
||||
T FindByPoNo(string pono);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
T FirstOrDefaultByPO(string ponr);
|
||||
|
||||
T FindFirstOrDefault(int standardId, int pono, int? pcbId);
|
||||
|
||||
void Unapprove(int id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
IEnumerable<T> Filter(StandardRequiremetnsFilter filter);
|
||||
|
||||
T FirstOrDefaultByKey(string key);
|
||||
|
||||
T FirstOrDefaultByPO(string ponr);
|
||||
|
||||
void Unapprove(int id);
|
||||
|
||||
@ -56,17 +56,158 @@
|
||||
FROM Cordonel_Requirements AS cr
|
||||
JOIN AlleAuftragPositionen AS aap
|
||||
ON cr.IdentNr = aap.IdentNr
|
||||
AND (cr.PoNr = aap.FertigungsauftragNr OR cr.PoNr IS NULL)
|
||||
JOIN AuftragPositionSerienNr AS aps
|
||||
ON aap.AuftragNr = aps.AuftragNr
|
||||
AND aap.PositionNr = aps.PositionNr
|
||||
JOIN MapPcbIdToSerialNumber AS map
|
||||
ON aps.SerienNr = map.MapPcbIdToSerialNumber_SerialNumber
|
||||
WHERE map.MapPcbIdToSerialNumber_PcbId = @{nameof(pcbid)}
|
||||
AND (cr.PoNr = aap.FertigungsauftragNr OR cr.PoNr IS NULL)
|
||||
AND (cr.PcbId = map.MapPcbIdToSerialNumber_PcbId OR cr.PcbId IS NULL)
|
||||
WHERE map.MapPcbIdToSerialNumber_PcbId = @{nameof(pcbid)}")
|
||||
ORDER BY cr.StandardId DESC
|
||||
, cr.SpecialId DESC")
|
||||
.SetParameter(nameof(pcbid), pcbid)
|
||||
.FirstOrDefault(this.ParseCordonelRequirements);
|
||||
|
||||
public CordonelRequirements FindByPcbIdFull(string pcbid, out string error)
|
||||
{
|
||||
error = default(string);
|
||||
|
||||
var requirements = default(CordonelRequirements);
|
||||
var pono = default(int?);
|
||||
var pcb = default(int?);
|
||||
|
||||
this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
SELECT DISTINCT
|
||||
cap.CordonelAssignedPicking_FertigungsAuftragsNr
|
||||
, map.MapPcbIdToSerialNumber_PcbId
|
||||
FROM Cordonel_AssignedPicking AS cap
|
||||
JOIN MapPcbIdToSerialNumber AS map
|
||||
ON cap.CordonelAssignedPicking_PcbId = map.MapPcbIdToSerialNumber_PcbId
|
||||
WHERE cap.CordonelAssignedPicking_PcbId = @{nameof(pcbid)}")
|
||||
.SetParameter(nameof(pcbid), pcbid)
|
||||
.FirstOrDefault(x =>
|
||||
{
|
||||
pono = x.GetValue<int?>(0);
|
||||
pcb = x.GetValue<int?>(1);
|
||||
});
|
||||
|
||||
if (pono is null)
|
||||
{
|
||||
error = $"Fertigungsauftragnr nicht gefunden für pcbId: {pcbid}";
|
||||
}
|
||||
else if (pcb is null)
|
||||
{
|
||||
error = $"PcbId: {pcbid} nicht gefunden";
|
||||
}
|
||||
|
||||
var identnr = default(int?);
|
||||
var menge = default(int?);
|
||||
var key = default(string);
|
||||
|
||||
this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
SELECT aap.IdentNr
|
||||
, aap.Menge
|
||||
, SUBSTRING(idn.VakoCode, 4, 2)
|
||||
FROM AlleAuftragPositionen AS aap
|
||||
JOIN Identnr AS idn
|
||||
ON aap.IdentNr = idn.IdentNr
|
||||
WHERE aap.FertigungsauftragNr = @{nameof(pono)}")
|
||||
.SetParameter(nameof(pono), pono)
|
||||
.FirstOrDefault(x =>
|
||||
{
|
||||
identnr = x.GetValue<int?>(0);
|
||||
menge = x.GetValue<int?>(1);
|
||||
key = x.GetValue<string>(2);
|
||||
});
|
||||
|
||||
if (identnr is null)
|
||||
{
|
||||
error = $"Identnr nicht gefunden für Fertigungsauftragnr: {pono}";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
else if (menge is null)
|
||||
{
|
||||
error = $"Menge ist ungültig für Fertigungsauftragnr: {pono}";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
else if (key is null)
|
||||
{
|
||||
error = $"Region-Size key ist ungültig für Fertigungsauftragnr: {pono}";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
|
||||
var standardRequirement = this.dbContext.StandardRequirements.FirstOrDefaultByKey(key);
|
||||
|
||||
if (standardRequirement is null)
|
||||
{
|
||||
error = $"Standardvreigabe für Size-Region: {key} nicht gefunden";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
else if (!standardRequirement.IsActive)
|
||||
{
|
||||
error = $"Standardvreigabe {standardRequirement.Id}.{standardRequirement.Version} nicht active";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
else if (standardRequirement.ApprovedDate is null)
|
||||
{
|
||||
error = $"Standardvreigabe {standardRequirement.Id}.{standardRequirement.Version} nicht genehmigt";
|
||||
|
||||
return requirements;
|
||||
}
|
||||
|
||||
var specialRequirement = this.dbContext.SpecialRequirements.FindFirstOrDefault(standardRequirement.Id, pono.Value, pcb);
|
||||
|
||||
if (specialRequirement?.ApprovedDate is null)
|
||||
{
|
||||
specialRequirement = default(CordonelSpecialRequirement);
|
||||
}
|
||||
|
||||
requirements = new CordonelRequirements
|
||||
{
|
||||
ApprovalComment = specialRequirement?.Comment ?? standardRequirement?.Comment,
|
||||
ApprovalName = specialRequirement?.ApprovedBy ?? standardRequirement?.ApprovedBy,
|
||||
EstimatedProductionBatteryLoadPercent = specialRequirement?.EstimatedProductionBatteryLoadPercent ?? standardRequirement?.EstimatedProductionBatteryLoadPercent,
|
||||
FwVersion = specialRequirement?.FwVersion ?? standardRequirement?.FwVersion,
|
||||
IsSpecialApproved = specialRequirement?.ApprovedDate != null,
|
||||
IsSpecialActive = specialRequirement?.IsActive ?? default(bool?),
|
||||
IsStandardActive = standardRequirement?.IsActive,
|
||||
IsStandardApproved = standardRequirement?.ApprovedDate != null,
|
||||
LutCrc = specialRequirement?.LutCrc ?? standardRequirement?.LutCrc,
|
||||
MaxDrainedBatteryLoadPercentAssembly = specialRequirement?.MaxDrainedBatteryLoadPercentAssembly ?? standardRequirement?.MaxDrainedBatteryLoadPercentAssembly,
|
||||
MaxDrainedBatteryLoadPercentShipping = specialRequirement?.MaxDrainedBatteryLoadPercentShipping ?? standardRequirement?.MaxDrainedBatteryLoadPercentShipping,
|
||||
MaxStorageMonths = menge < 5
|
||||
? specialRequirement?.MaxStorageMonths ?? standardRequirement?.MaxStorageMonths
|
||||
: specialRequirement?.MaxStorageMonthsBigOrders ?? standardRequirement?.MaxStorageMonthsBigOrders,
|
||||
MeterSize = specialRequirement?.MeterSize ?? standardRequirement?.MeterSize,
|
||||
OuterPcbId = pcb,
|
||||
OuterProductionOrderNr = pono,
|
||||
PcbId = specialRequirement?.PcbId,
|
||||
ProductionOrderNr = specialRequirement?.ProductionOrderNr,
|
||||
QuiescentCurrent_uA = specialRequirement?.QuiescentCurrent_uA ?? standardRequirement?.QuiescentCurrent_uA,
|
||||
Region = specialRequirement?.Region ?? standardRequirement?.Region,
|
||||
RegionSizeKey = key,
|
||||
RequiredLifeTimeYearsAssembly = specialRequirement?.RequiredLifeTimeYearsAssembly ?? standardRequirement?.RequiredLifeTimeYearsAssembly,
|
||||
RequiredLifeTimeYearsShipping = specialRequirement?.RequiredLifeTimeYearsShipping ?? standardRequirement?.RequiredLifeTimeYearsShipping,
|
||||
RequirementTimestamp = specialRequirement?.Timestamp ?? standardRequirement?.Timestamp,
|
||||
SkipCalibration = specialRequirement?.SkipCalibration ?? standardRequirement?.SkipCalibration ?? false,
|
||||
SkipRadioCheck = specialRequirement?.SkipRadioCheck ?? standardRequirement?.SkipRadioCheck ?? false,
|
||||
SpecialId = specialRequirement?.Id,
|
||||
SpecialVersion = specialRequirement?.Version,
|
||||
StandardId = standardRequirement?.Id,
|
||||
StandardVersion = standardRequirement?.Version,
|
||||
};
|
||||
|
||||
return requirements;
|
||||
}
|
||||
|
||||
public CordonelRequirements FindByPoNo(string pono)
|
||||
=> this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
@ -106,14 +247,16 @@
|
||||
FROM Cordonel_Requirements AS cr
|
||||
JOIN AlleAuftragPositionen AS aap
|
||||
ON cr.IdentNr = aap.IdentNr
|
||||
AND (cr.PoNr = aap.FertigungsauftragNr OR cr.PoNr IS NULL)
|
||||
JOIN AuftragPositionSerienNr AS aps
|
||||
ON aap.AuftragNr = aps.AuftragNr
|
||||
AND aap.PositionNr = aps.PositionNr
|
||||
JOIN MapPcbIdToSerialNumber AS map
|
||||
ON aps.SerienNr = map.MapPcbIdToSerialNumber_SerialNumber
|
||||
WHERE aap.FertigungsauftragNr = @{nameof(pono)}
|
||||
AND (cr.PoNr = aap.FertigungsauftragNr OR cr.PoNr IS NULL)
|
||||
AND (cr.PcbId = map.MapPcbIdToSerialNumber_PcbId OR cr.PcbId IS NULL)
|
||||
WHERE aap.FertigungsauftragNr = @{nameof(pono)}")
|
||||
ORDER BY cr.StandardId DESC
|
||||
, cr.SpecialId DESC")
|
||||
.SetParameter(nameof(pono), pono)
|
||||
.FirstOrDefault(this.ParseCordonelRequirements);
|
||||
|
||||
|
||||
@ -402,6 +402,47 @@
|
||||
return requirement;
|
||||
}
|
||||
|
||||
public CordonelSpecialRequirement FindFirstOrDefault(int standardId, int pono, int? pcbId)
|
||||
=> this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
SELECT [Special].[Id]
|
||||
, [Special].[Version]
|
||||
, [Special].[StandardId]
|
||||
, [Special].[StandardVersion]
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, [Special].[ProductionOrderNo]
|
||||
, [Special].[PcbId]
|
||||
, [Special].[FwVersion]
|
||||
, [Special].[LutCrc]
|
||||
, [Special].[SkipCalibration]
|
||||
, [Special].[SkipRadioCheck]
|
||||
, [Special].[RequiredLifeTimeYearsAssembly]
|
||||
, [Special].[RequiredLifeTimeYearsShipping]
|
||||
, [Special].[MaxDrainedBatteryLoadPercentAssembly]
|
||||
, [Special].[MaxDrainedBatteryLoadPercentShipping]
|
||||
, [Special].[MaxStorageMonths]
|
||||
, [Special].[MaxStorageMonthsBigOrders]
|
||||
, [Special].[QuiescentCurrent_uA]
|
||||
, [Special].[EstimatedProductionBatteryLoadPercent]
|
||||
, [Special].[Timestamp]
|
||||
, [Special].[CreatedBy]
|
||||
, [Special].[ApprovedBy]
|
||||
, [Special].[ApprovedDate]
|
||||
, [Special].[Comment]
|
||||
, [Special].[IsActive]
|
||||
, NULL
|
||||
FROM [Cordonel_Special_Requirements] AS [Special]
|
||||
WHERE [Special].[StandardId] = @{nameof(standardId)}
|
||||
AND [Special].[ProductionOrderNo] = @{nameof(pono)}
|
||||
AND ([Special].[PcbId] = @{nameof(pcbId)} OR [Special].[PcbId] IS NULL)
|
||||
ORDER BY [Special].[Version] DESC")
|
||||
.SetParameter(nameof(standardId), standardId)
|
||||
.SetParameter(nameof(pono), pono)
|
||||
.SetParameter(nameof(pcbId), pcbId)
|
||||
.FirstOrDefault(this.ParseSpecialRequirement);
|
||||
|
||||
public CordonelSpecialRequirement FirstOrDefaultByPO(string ponr)
|
||||
{
|
||||
var id = default(int?);
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
public class StandardRequirementsRepository : IStandardRequirementRepository<CordonelStandardRequirement>
|
||||
@ -428,5 +427,39 @@
|
||||
.CreateCommand(query)
|
||||
.ExecuteReader(this.ParseStandardRequirement);
|
||||
}
|
||||
|
||||
public CordonelStandardRequirement FirstOrDefaultByKey(string key)
|
||||
=> this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
SELECT TOP 1
|
||||
[STD].[Id]
|
||||
, [STD].[Version]
|
||||
, [STD].[Key]
|
||||
, [STD].[Region]
|
||||
, [STD].[ProductGroup]
|
||||
, [STD].[MeterSize]
|
||||
, [STD].[FwVersion]
|
||||
, [STD].[LutCrc]
|
||||
, [STD].[SkipCalibration]
|
||||
, [STD].[SkipRadioCheck]
|
||||
, [STD].[RequiredLifeTimeYearsAssembly]
|
||||
, [STD].[RequiredLifeTimeYearsShipping]
|
||||
, [STD].[MaxDrainedBatteryLoadPercentAssembly]
|
||||
, [STD].[MaxDrainedBatteryLoadPercentShipping]
|
||||
, [STD].[MaxStorageMonths]
|
||||
, [STD].[MaxStorageMonthsBigOrders]
|
||||
, [STD].[QuiescentCurrent_uA]
|
||||
, [STD].[EstimatedProductionBatteryLoadPercent]
|
||||
, [STD].[Timestamp]
|
||||
, [STD].[CreatedBy]
|
||||
, [STD].[ApprovedBy]
|
||||
, [STD].[ApprovedDate]
|
||||
, [STD].[Comment]
|
||||
, [STD].[IsActive]
|
||||
FROM [Cordonel_Standard_Requirements] AS [STD]
|
||||
WHERE [STD].[Key] = @{nameof(key)}
|
||||
ORDER BY [STD].[Version] DESC")
|
||||
.SetParameter(nameof(key), key)
|
||||
.FirstOrDefault(this.ParseStandardRequirement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,12 @@
|
||||
[Route("pcbid/{pcbid}")]
|
||||
public IHttpActionResult PCBID(string pcbid)
|
||||
{
|
||||
var requirement = this.cordonels.Requirements.FindByPcbId(pcbid);
|
||||
var requirement = this.cordonels.Requirements.FindByPcbIdFull(pcbid, out string error);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
return this.BadRequest(error);
|
||||
}
|
||||
|
||||
return this.Json(requirement, new JsonSerializerSettings
|
||||
{
|
||||
|
||||
@ -2,7 +2,11 @@
|
||||
<configuration>
|
||||
|
||||
<appSettings>
|
||||
|
||||
<add key="webpages:Version" value="3.0.0.0" />
|
||||
|
||||
|
||||
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
<add key="ClientValidationEnabled" value="true" />
|
||||
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user