Skip to content

Commit

Permalink
Added possibility to update existing attributes, and set seed.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Rapp committed Oct 1, 2017
1 parent 4a1cf6a commit 07b2ee5
Show file tree
Hide file tree
Showing 9 changed files with 427 additions and 146 deletions.
28 changes: 28 additions & 0 deletions AttributeProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Microsoft.Xrm.Sdk.Metadata;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Rappen.XTB.AutoNumManager
{
public class AttributeProxy
{
internal StringAttributeMetadata attributeMetadata;

public AttributeProxy(StringAttributeMetadata metadata)
{
attributeMetadata = metadata;
}

public string Attribute { get { return attributeMetadata.LogicalName; } }

public string Format { get { return attributeMetadata.AutoNumberFormat; } }

public override string ToString()
{
return attributeMetadata.LogicalName;
}
}
}
5 changes: 2 additions & 3 deletions AutoNumManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Cinteros.Xrm.CRMWinForm, Version=2017.9.4.18, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Cinteros.Xrm.CRMWinForm.2017.9.4.18\lib\net452\Cinteros.Xrm.CRMWinForm.dll</HintPath>
</Reference>
<Reference Include="McTools.Xrm.Connection, Version=1.2017.5.14, Culture=neutral, PublicKeyToken=96037217801d9658, processorArchitecture=MSIL">
<HintPath>packages\MscrmTools.Xrm.Connection.1.2017.5.14\lib\net452\McTools.Xrm.Connection.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -104,13 +101,15 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AttributeProxy.cs" />
<Compile Include="AutoNumMgr.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="AutoNumMgr.Designer.cs">
<DependentUpon>AutoNumMgr.cs</DependentUpon>
</Compile>
<Compile Include="EntityMetadataProxy.cs" />
<Compile Include="MetadataHelper.cs" />
<Compile Include="PluginInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings.cs" />
Expand Down
215 changes: 119 additions & 96 deletions AutoNumMgr.Designer.cs

Large diffs are not rendered by default.

206 changes: 169 additions & 37 deletions AutoNumMgr.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Cinteros.Xrm.CRMWinForm;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;
Expand All @@ -11,6 +10,8 @@
using XrmToolBox.Extensibility;
using XrmToolBox.Extensibility.Interfaces;
using XrmToolBox.Extensibility.Args;
using System.ComponentModel;
using Microsoft.Crm.Sdk.Messages;

namespace Rappen.XTB.AutoNumManager
{
Expand Down Expand Up @@ -137,7 +138,10 @@ private void LoadEntities()
if (completedargs.Result is RetrieveMetadataChangesResponse)
{
var metaresponse = ((RetrieveMetadataChangesResponse)completedargs.Result).EntityMetadata;
entities.AddRange(metaresponse.Select(m => new EntityMetadataProxy(m)).OrderBy(e => e.ToString()));
entities.AddRange(metaresponse
.Where(e => e.IsCustomizable.Value == true && e.IsIntersect.Value != true)
.Select(m => new EntityMetadataProxy(m))
.OrderBy(e => e.ToString()));
}
}
EnableControls(true);
Expand All @@ -148,11 +152,11 @@ private void LoadEntities()
private void FilterEntities()
{
cmbEntities.Items.Clear();
if (!(cmbSolution.SelectedItem is SolutionProxy))
var solution = cmbSolution.SelectedItem as SolutionProxy;
if (solution == null)
{
return;
}
var solution = ((SolutionProxy)cmbSolution.SelectedItem);
lblPrefix.Text = solution.Prefix;
WorkAsync(new WorkAsyncInfo("Filtering entities...",
(eventargs) =>
Expand Down Expand Up @@ -185,6 +189,22 @@ private void FilterEntities()
});
}

private void LoadAttributes()
{
gridAttributes.DataSource = null;
var entity = cmbEntities.SelectedItem as EntityMetadataProxy;
var details = MetadataHelper.LoadEntityDetails(Service, entity.Metadata.LogicalName).EntityMetadata.FirstOrDefault();
if (details != null)
{
var attributes = details.Attributes
.Where(a => a.AttributeType == AttributeTypeCode.String && !string.IsNullOrEmpty(a.AutoNumberFormat))
.Select(a => new AttributeProxy((StringAttributeMetadata)a)).ToList();
var bindingList = new BindingList<AttributeProxy>(attributes);
var source = new BindingSource(bindingList, null);
gridAttributes.DataSource = source;
}
}

private void LoadUserSettings()
{
var qx = new QueryExpression("usersettings");
Expand All @@ -199,11 +219,53 @@ private void LoadUserSettings()

private void btnCreateNew_Click(object sender, EventArgs e)
{
if (DialogResult.OK != MessageBox.Show("Confirm creation!", "Confirm", MessageBoxButtons.OKCancel))
if (DialogResult.OK != MessageBox.Show("Confirm!", "Confirm", MessageBoxButtons.OKCancel))
{
return;
}
ExecuteMethod(CreateAttribute);
if (txtLogicalName.Enabled)
{
ExecuteMethod(CreateAttribute);
}
else
{
ExecuteMethod(UpdateAttribute);
}
}

private void UpdateAttribute()
{
var langid = int.Parse(txtLanguageId.Text);
var attributename = lblPrefix.Text + txtLogicalName.Text;
var req = new UpdateAttributeRequest
{
EntityName = ((EntityMetadataProxy)cmbEntities.SelectedItem).Metadata.LogicalName,
Attribute = new StringAttributeMetadata
{
AutoNumberFormat = txtNumberFormat.Text,
LogicalName = attributename,
SchemaName = attributename,
RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
MaxLength = int.Parse(txtMaxLen.Text),
DisplayName = new Microsoft.Xrm.Sdk.Label(txtDisplayName.Text, langid),
Description = new Microsoft.Xrm.Sdk.Label(txtDescription.Text, langid)
},
SolutionUniqueName = (cmbSolution.SelectedItem as SolutionProxy)?.UniqueName
};

try
{
Service.Execute(req);
if (!string.IsNullOrEmpty(txtSeed.Text) && txtSeed.Text != "1")
{
SetSeed();
}
MessageBox.Show("Attribute updated!");
}
catch (Exception ex)
{
MessageBox.Show($"Update failed:\n{ex}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

private void CreateAttribute()
Expand All @@ -223,12 +285,16 @@ private void CreateAttribute()
DisplayName = new Microsoft.Xrm.Sdk.Label(txtDisplayName.Text, langid),
Description = new Microsoft.Xrm.Sdk.Label(txtDescription.Text, langid)
},
SolutionUniqueName = cmbSolution.Text
SolutionUniqueName = (cmbSolution.SelectedItem as SolutionProxy)?.UniqueName
};

try
{
var resp = (CreateAttributeResponse)Service.Execute(req);
Service.Execute(req);
if (!string.IsNullOrEmpty(txtSeed.Text) && txtSeed.Text != "1")
{
SetSeed();
}
MessageBox.Show("Attribute created!");
}
catch (Exception ex)
Expand All @@ -237,6 +303,25 @@ private void CreateAttribute()
}
}

private void SetSeed()
{
var attributename = lblPrefix.Text + txtLogicalName.Text;
var req = new SetAutoNumberSeedRequest
{
EntityName = ((EntityMetadataProxy)cmbEntities.SelectedItem).Metadata.LogicalName,
AttributeName = attributename,
Value = int.Parse(txtSeed.Text)
};
try
{
Service.Execute(req);
}
catch (Exception ex)
{
MessageBox.Show($"Seed update failed:\n{ex}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var help = @"AutoNumberFormat value Example value
Expand All @@ -263,60 +348,63 @@ private void cmbSolution_SelectedIndexChanged(object sender, EventArgs e)
private void cmbEntities_SelectedIndexChanged(object sender, EventArgs e)
{
gbNewAttribute.Enabled = cmbEntities.SelectedItem is EntityMetadataProxy;
LoadAttributes();
}

private void txtNumberFormat_TextChanged(object sender, EventArgs e)
{
txtSample.Text = ParseNumberFormat(txtNumberFormat.Text);
txtSample.Text = ParseNumberFormat(txtNumberFormat.Text, txtSeed.Text);
}

private string ParseNumberFormat(string format)
private void txtSeed_TextChanged(object sender, EventArgs e)
{
txtSample.Text = ParseNumberFormat(txtNumberFormat.Text, txtSeed.Text);
}

private string ParseNumberFormat(string format, string seed)
{
try
{
VerifySEQNUM(format);
format = ParseFormatSEQNUM(format);
format = ParseFormatSEQNUM(format, seed);
format = ParseFormatRANDSTRING(format);
format = ParseFormatDATETIMEUTC(format);
SendMessageToStatusBar(this, new StatusBarMessageEventArgs("Format successfully parsed"));
btnCreateNew.Enabled = true;
}
catch (Exception ex)
{
SendMessageToStatusBar(this, new StatusBarMessageEventArgs(ex.Message));
format = $"Format error: {ex.Message}";
btnCreateNew.Enabled = false;
}

return format;
}

private void VerifySEQNUM(string format)
private string ParseFormatSEQNUM(string format, string seed)
{
var numbered = ParseFormatSEQNUM(format);
if (numbered.Equals(format))
if (!format.Contains("{SEQNUM:") || !format.Contains("}"))
{
throw new FormatException("Format string must contain at least one {SEQNUM:n} placeholder.");
throw new FormatException("Format string must contain a {SEQNUM:n} placeholder.");
}
}

private string ParseFormatSEQNUM(string format)
{
while (format.Contains("{SEQNUM:") && format.Contains("}"))
var lenghtstr = format.Split(new string[] { "{SEQNUM:" }, StringSplitOptions.None)[1];
lenghtstr = lenghtstr.Split('}')[0];
if (int.TryParse(lenghtstr, out int length))
{
var lenghtstr = format.Split(new string[] { "{SEQNUM:" }, StringSplitOptions.None)[1];
lenghtstr = lenghtstr.Split('}')[0];
if (int.TryParse(lenghtstr, out int length))
if (length < 1)
{
if (length < 1)
{
throw new FormatException("SEQNUM length must be 1 or higher.");
}
var sequence = "0123456789".Substring(0, length);
format = format.Replace("{SEQNUM:" + lenghtstr + "}", sequence);
}
else
{
throw new FormatException("Invalid SEQNUM format. Enter as {SEQNUM:n} where n is length of sequence.");
throw new FormatException("SEQNUM length must be 1 or higher.");
}
var seedno = string.IsNullOrEmpty(seed) ? 1 : int.Parse(seed);
var sequence = string.Format("{0:" + new string('0', length) + "}", seedno);
format = format.Replace("{SEQNUM:" + lenghtstr + "}", sequence);
}
else
{
throw new FormatException("Invalid SEQNUM format. Enter as {SEQNUM:n} where n is length of sequence.");
}
if (format.Contains("{SEQNUM:"))
{
throw new FormatException("Format string must only contain one {SEQNUM:n} placeholder.");
}
return format;
}
Expand Down Expand Up @@ -383,9 +471,53 @@ private void llRandom_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e
AddMacro("{RANDSTRING:4}");
}

private void button1_Click(object sender, EventArgs e)
private void btnNew_Click(object sender, EventArgs e)
{
lblPrefix.Text = (cmbSolution.SelectedItem as SolutionProxy)?.Prefix;
txtLogicalName.Enabled = true;
txtLogicalName.Text = string.Empty;
txtDisplayName.Text = string.Empty;
txtDescription.Text = string.Empty;
txtMaxLen.Text = "100";
txtNumberFormat.Text = "{SEQNUM:5}";
txtSample.Text = ParseNumberFormat(txtNumberFormat.Text, "1");
txtSeed.Text = string.Empty;
btnCreateNew.Text = "Create";
gbNewAttribute.Enabled = true;
}

private void gridAttributes_SelectionChanged(object sender, EventArgs e)
{
gbNewAttribute.Enabled = false;
SendMessageToStatusBar(this, new StatusBarMessageEventArgs(string.Empty));
var grid = sender as DataGridView;
if (grid?.SelectedRows?.Count == 0)
{
return;
}
var row = grid.SelectedRows[0];
var attribute = row.DataBoundItem as AttributeProxy;
if (attribute == null)
{
return;
}
var logical = attribute.Attribute;
if (!logical.Contains("_"))
{
SendMessageToStatusBar(this, new StatusBarMessageEventArgs("Attribute does not seem to be custom."));
return;
}
lblPrefix.Text = logical.Split('_')[0] + "_";
txtLogicalName.Text = logical.Substring(logical.IndexOf("_") + 1);
txtDisplayName.Text = attribute.attributeMetadata.DisplayName?.UserLocalizedLabel?.Label;
txtDescription.Text = attribute.attributeMetadata.Description?.UserLocalizedLabel?.Label;
txtMaxLen.Text = attribute.attributeMetadata.MaxLength?.ToString();
txtNumberFormat.Text = attribute.attributeMetadata.AutoNumberFormat;
txtSample.Text = ParseNumberFormat(txtNumberFormat.Text, "1");
txtSeed.Text = string.Empty;
txtLogicalName.Enabled = false;
btnCreateNew.Text = "Update";
gbNewAttribute.Enabled = true;
}
}
}
12 changes: 12 additions & 0 deletions AutoNumMgr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,16 @@
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="Attribute.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Format.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Attribute.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Format.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>
Loading

0 comments on commit 07b2ee5

Please sign in to comment.