I just wanna ask if there is someone here that have already made a breadcrumbs in Sitecore. I'm currently doing a Sitecore 8 MVC project that needs to have a breadcrumbs.
Currently I saw this website http://blog.ryanbailey.co.nz/2015/05/breadcrumbs-for-pages-in-sitecore.html. But It doesn't work for me yet because I don't know what to reference.
I just need to know how to get every item in the path of my current page I can handle it already.
Thanks
Something like this should do it:
public ICollection<Item> GetBreadcrumbs(Item current, SiteContext site)
{
Item homeItem = site.StartItem;
List<Item> breadcrumbs = new List<Item>();
while (current != null)
{
// You may want to add additional logic to opt in/out of
// the breadcrumb based on a template/field
breadcrumbs.Add(current);
if (current == homeItem)
break;
current = current.Parent;
}
breadcrumbs.Reverse();
return breadcrumbs;
}
And then:
var breadcrumbs = GetBreadcrumbs(Context.Item, Context.Site);
You can take the current item and then take all the ancestors of it.
var ancestors = currentItem.Axes.GetAncestors().ToList();
Then you can get home item and filter the ancestors to remove sitecore and content nodes.
ancestors = ancestors.SkipWhile(i => i.ID != home.Id.ToID()).ToList();
public void GetBreadcrumbs(Item ParentItem)
{
List<BredCrumbDetails> lstBreadCrumbs = new List<BredCrumbDetails>();
string strcurrenttitle = ParentItem.Name;
Item currentitem = ParentItem;
int i = 0;
while (currentitem != null)
{
var ItemTemplateid = currentitem.TemplateID.ToString();
var FolderTemplateId = "{}";
if (ItemTemplateid != FolderTemplateId) //here we are removing folders
{
BredCrumbDetails bcDetails = new BredCrumbDetails();
if (i == 0)
{
bcDetails.BCPageLink = null;
bcDetails.Title = currentitem.Name;
bcDetails.IsVisible = true;
lstBreadCrumbs.Add(bcDetails);
}
else
{
bcDetails.BCPageLink = currentitem.Paths.FullPath;
bcDetails.Title = currentitem.Name;
bcDetails.IsVisible = true;
lstBreadCrumbs.Add(bcDetails);
}
i++;
if (currentitem.Name == ("Home"))
{
break;
}
currentitem = currentitem.Parent;
}
else
{
i++;
currentitem = currentitem.Parent;
}
}
lstBreadCrumbs.Reverse();
rptCrumbs.DataSource = lstBreadCrumbs;
rptCrumbs.DataBind();
}
Related
This question has been asked before in different forms, but none answer my question. I have scraped this forum and Windows dev forum for info, before posting this. I cannot make sense of how to accomplish this task.
I am at my wits end.
I have a DataGrid that is binded to an ICollectionView. This data was pulled via a stored procedure and the DataGrid is automatically generated based on the columns in each table. For reference, the SP returns a list of objects, each with a series of members like stock_symbol, stock_price, Date etc.
There are a series of filters I would like to apply to this collection view. Two comboboxes and two datepickers, to be more specific. Each with a checkbox to signify they are active.
Each checkbox event handler stores the data that was selected from the combobox or the datepicker. I am trying to compare what is in those variables, to each relevant member of the object list and send that filtered object list back to the DataGrid.
This is my code:
private void FillDataGrid()
{
//Connect contains a simple stored procedure connection to SQL server
var Client = Connect();
DTOClass[] dTOs = Client.GetData();
SetDTOClass(dTOs);
MainGrid.ItemsSource = FilterView(dTOs);
}
Here is FilterView() (apologies for the long commented sections, I am trying to include my attempts in one foul sweep):
public ICollectionView /*List<DTOClass>*/ FilterView(DTOClass[] DTO)
{
if (_CollectionViewInternal == null)
{
//Assign collected DTO object to an ICollectionView
_CollectionViewInternal =
CollectionViewSource.GetDefaultView(DTO);
}
/*
ObservableCollection<DTOClass> DTOview = null;
if (DTOViewInternal == null)
{
int j = DTO.Length;
DTOview = new ObservableCollection<DTOClass>();
for(int i = 0; i < j; i++)
{
DTOview.Add(DTO[i]);
}
DTOViewInternal = DTOview;
}
*/
//Add a default sort description to the Date column
_CollectionViewInternal.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Ascending));
//assign our view to the maingrid (move this to later in the
//MainGrid.ItemsSource = _CollectionViewInternal;
if (MainGrid.ItemsSource != null)
{
/*List<Predicate<IEnumerable<DTOClass[]>>>*/ FilteredView = new List<Predicate<IEnumerable<DTOClass[]>>>();
//DateTime _zeroDay = new DateTime(1, 1, 1);
//DateTime _now = DateTime.Now;
FilteredView.Clear();
return FilteredView = _CollectionViewInternal.Where(Function(w) w.accountname.Contains(txtFilter.Text) _
Or w.firstname.Contains(txtFilter.Text) _
Or w.lastname.Contains(txtFilter.Text) _
Or w.isenabled.Contains(txtFilter.Text) _
Or w.description.Contains(txtFilter.Text) _
Or w.lastlogontimestamp.Contains(txtFilter.Text) _
Or w.whencreated.Contains(txtFilter.Text) _
Or w.whenchanged.Contains(txtFilter.Text) _
Or w.oulocation.Contains(txtFilter.Text) _
Or w.co.Contains(txtFilter.Text) _
Or w.l.Contains(txtFilter.Text) _
Or w.state.Contains(txtFilter.Text))
//if (yearsChosen > 0)
/* Stock, Maxadj, FromDate, ToDate */
/*
if (Stock_CheckBox.IsChecked != null)
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Where(item => item. == Stock_ComboBoxText)));
}
if (letterChosen != "Any")
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.LastName.StartsWith(letterChosen)));
}
if (genderChosen != "Any")
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Gender.Equals(genderChosen.Substring(0, 1))));
}
_CollectionViewInternal.Filter = dynamic_Filter;
RaisePropertyChanged("PeopleView");
// Bring the current person back into view in case it moved
if (CurrentPerson != null)
{
IEnumerable<DTOClass[]> current = CurrentPerson;
_CollectionViewInternal.MoveCurrentToFirst();
_CollectionViewInternal.MoveCurrentTo(current);
}
*/
/*
if (DTOview == null)
{
DTOview = DTOViewInternal;
} else
{
DTOViewInternal.
}
*/
//var collection = DTO;
//var symbol = collection.Where(item => item.Date == ).ToList();
//DTOview = new ObservableCollection<DTOClass>();
//IEnumerable<DTOClass> DTOview2;
//List<IEnumerable<DTOClass>> FilteredView = new List<IEnumerable<DTOClass>>();
/*
if (Stock_ComboBoxText != null)
{
//var collection = DTO;
var collection = DTO.Where(item => item.stock_symbol == Stock_ComboBoxText).Cast<DTOClass>().ToList();
//DTOview.Add(filtered.Cast<DTOClass>());
//FilteredView.Add(collection.Cast<DTOClass>());
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
//FilteredView = filtered.Cast<DTOClass>();
}
if (Maxadj_ComboBoxText != 0)
{
var collection = DTO.Where(item => item.stock_price_adj_close == Maxadj_ComboBoxText).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
//DTOview.Add(DTO.Where(item => item.stock_price_adj_close == ).ToList());
}
if (From_DatePickValue != null)
{
var collection = DTO.Where(item => item.Date >= From_DatePickValue).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
}
if (To_DatePickValue != null)
{
var collection = DTO.Where(item => item.Date <= To_DatePickValue).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
}
*/
//DTOview = DTOViewInternal;
//DTOview = null;
//DTOClass[] dto = GetDTOClass();
//ListCollectionView collectionView = new ListCollectionView(DTOViewInternal);
/*
collectionView.Filter = (e) =>
{
//int j = DTO.Length;
DTOClass[] dtofiltered = e as DTOClass[];
//for (int i = 0; i < j; i++)
//{
if ((Stock_ComboBoxText != null) && (DTOview[0][i].stock_symbol == Stock_ComboBoxText))
{
return true;
}
if ((Maxadj_ComboBoxText != 0) && (DTOview[0][i].stock_price_adj_close == Maxadj_ComboBoxText))
{
return true;
}
if ((From_DatePickValue != null) && (DTOview[0][i].Date >= From_DatePickValue))
{
return true;
}
if ((To_DatePickValue != null) && (DTOview[0][i].Date <= To_DatePickValue))
{
return true;
}
}
return true;
};
*/
//return collectionView.Cast<DTOClass>().ToList();
//return collectionView.Filter;
//return null;
//MainGrid.ItemsSource = null;
//MainGrid.ItemsSource = (CollectionView)CollectionViewSource.GetDefaultView(collectionView.ToString());
}
else
{
//MainGrid.ItemsSource = DTOview[0].ToList();
//MainGrid.ItemsSource = DTOview;
//return DTOview[0].ToList();
return _CollectionViewInternal;
}
return _CollectionViewInternal;
}
I only want to filter on a column, if it's relevant checkbox is checked. This is easy pickings with one filter, but more than one is proving to be beyond challenging.
As you can see I have attempted numerous solutions. I have tried using an ObservableCollection, I have tried filtering the object list directly and then adding it to an ICollectionView. Nothing works.
I have been attempting to graft this example: Complicated Filtering ICollectionView. But I cannot make heads or tails of it. I still don't understand predicates and tbh I really can't wrap my head around how it works.
I know it's frowned upon to ask 'gimme the code' questions. But if someone could just see past that and point out what I am doing wrong here, maybe even give me the code, I would be very grateful. I have spent weeks trying to understand this and I have run out of time on this assignment.
If not, then that's cool but please refrain from commenting on this thread. Don't take pride in withholding the answer either, I am usually an embedded C programmer and I just finished a full-sized OSX-Windows port for a massive Adobe AfterFX plugin. So I don't need snide remarks or any nonsense about putting more effort into learning, I just want to finish this assignment and be done with it.
Thank you all in advance.
Code to complement above comment:
List<Predicate<IEnumerable<DTOClass[]>>> FilteredView = null;
public ICollectionView FilterView(DTOClass[] DTO)
{
List<Predicate<IEnumerable<DTOClass[]>>>FilteredView = new
List<Predicate<IEnumerable<DTOClass[]>>>();
FilteredView.Clear();
if (Stock_CheckBox.IsChecked != null)
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Where(item => item.stock_symbol == Stock_ComboBoxText)));
}
}
I can't even get the first predicate working. Apparently .stock_symbol isn't there and I can't index item. I suppose my real question here is how do I access the stock_symbol member?
Apologies for taking so long to get there, I am extremely sleep deprived.
EDIT:
Dumb mistakes are made with no sleep.
List<Predicate<DTOClass>> FilteredView = new List<Predicate<DTOClass>>();
if (Stock_CheckBox.IsChecked != null)
{
for (int i = 0; i < DTO.Length; i++)
{
FilteredView.Add(new Predicate<DTOClass>(x => x.stock_symbol == _Stock_ComboBoxText));
//FilteredView.Add(new Predicate<DTOClass[]>>(x => x.stock_symbol == _Stock_ComboBoxText));
}
}
I have two observable collections. 1. TruckItems 2. TruckItemsComparison. Both are exactly the same.
I load data into the first TruckItems collection from EF6, then 10 seconds later I load data into the second collection TruckItemsComparison. Now the new data that was added in my 2nd collection might have been updated lately from another source and I need to only add the latest data that does not yet exist in my first collection.
I want to check if ANY of the id's from my 2nd collection does not match any of the id's in my first collection and then only add the items that does not match.
CODE:
Here is where I load my data:
private async void LoadTrucks()
{
using (TruckServiceClient service = new TruckServiceClient())
{
var items = await service.GetTrucksAsync();
if (TruckItems.Count == 0)
{
foreach (var item in items)
{
TruckItems.Add(new TruckItems
{
TruckId = item.TruckId,
TruckQuoteId = item.QuoteId,
TruckPhaseId = item.CurrentPhaseId,
TruckChassisManufacturer = item.ChassisManufacturer,
TruckChassisModel = item.ChassisModel,
TruckStatus = item.Status,
TruckJobNumber = item.JobNumbers,
TruckAddedBy = item.AddedBy,
TruckClientName = item.ClientName,
TruckClientSurname = item.ClientSurname,
TruckClientDetail = item.ClientDetail,
TruckCurrentPhase = item.CurrentPhase
});
}
}
foreach (var item in items)
{
TruckItemsComparison.Add(new TruckItems
{
TruckId = item.TruckId,
TruckQuoteId = item.QuoteId,
TruckPhaseId = item.CurrentPhaseId,
TruckChassisManufacturer = item.ChassisManufacturer,
TruckChassisModel = item.ChassisModel,
TruckStatus = item.Status,
TruckJobNumber = item.JobNumbers,
TruckAddedBy = item.AddedBy,
TruckClientName = item.ClientName,
TruckClientSurname = item.ClientSurname,
TruckClientDetail = item.ClientDetail,
TruckCurrentPhase = item.CurrentPhase
});
}
}
}
And here is where I want to compare my two collections:
public void UpdateTrucks()
{
LoadTrucks();
if (TruckItems.Count != 0)
{
var truckItemsId = TruckItems.Where(x => x.TruckId != 0).First().TruckId;
foreach (var item in TruckItemsComparison.Where(x => x.TruckId != truckItemsId))
{
TruckItems.Add(item);
}
}
}
My problem is that it adds the data from both the two collections together, regardless if the id's correspond or not. Clearly my logic here does not work, so can anyone please show me a way of how I can compare the data and only insert id's that do not yet exist in my TruckItems collection. Thanks and please let me know if you need any more information.
You can enumerate through each of the items in your TruckItemsComparison by using Except:
public void UpdateTrucks()
{
LoadTrucks();
if (TruckItems.Count != 0)
{
foreach (var item in TruckItemsComparison.Except(TruckItems))
{
TruckItems.Add(item);
}
}
}
If all you want to do is compare the Ids of your TruckItems then you can implement your own IEqualityComparer:
internal class TruckItemsComparer : IEqualityComparer<TruckItems>
{
#region IEqualityComparer Members
public bool Equals(TruckItems x, TruckItems y)
{
return (((x == null) && (y == null)) ||
((x != null) && (y != null) && x.TruckId == y.TruckId));
}
public int GetHashCode(TruckItems obj)
{
return obj. TruckId.GetHashCode();
}
#endregion
}
And then use like so:
foreach (var item in TruckItemsComparison.Except(TruckItems, new TruckItemsComparer()))
I have two tables Rule and RuleCondition (one -> many).
people can add conditions at any time.
Suppose initially he adds two conditions.
He can comeback and add another condition also can update the conditions that are already added.
I am able to save the updated conditions, but not able to insert the extra condition he added.
Below is my code, and it is failing at
rule.RuleConditions.Add(oRuleCon); -- Entity set was modified during enumaration
If I use the approach
oAngieCtxt.RuleConditions.InsertOnSubmit(oRuleCon);
it is not at all inserting the data.
can somebody advise how to handle?
public ActionResult saveMetricRule(Rule rule)
{
bool IsNew = rule.RuleId == 0;
using (NewAngieDataContext oAngieCtxt = new NewAngieDataContext(new CSConfigurationMgr().GetConnectionString(ConnectionStringKey.Angie)))
{
if (IsNew)
oAngieCtxt.Rules.InsertOnSubmit(rule);
else
{
RuleCondition oRuleCon = null;
foreach (RuleCondition childItem in rule.RuleConditions)
{
if (childItem.RuleConditionId == 0)
{
oRuleCon = new RuleCondition();
oRuleCon.Points = childItem.Points;
oRuleCon.ConditionValue = childItem.ConditionValue;
oRuleCon.ToOperatorId = childItem.ToOperatorId;
oRuleCon.Sort = childItem.Sort;
rule.RuleConditions.Add(oRuleCon);
// oAngieCtxt.RuleConditions.InsertOnSubmit(oRuleCon);
}
else
{
oRuleCon =
oAngieCtxt.RuleConditions
.Where(CON => CON.RuleConditionId == childItem.RuleConditionId)
.FirstOrDefault();
oRuleCon.Points = childItem.Points;
oRuleCon.ConditionValue = childItem.ConditionValue;
oRuleCon.ToOperatorId = childItem.ToOperatorId;
oRuleCon.Sort = childItem.Sort;
}
}
oAngieCtxt.Rules.Attach(rule);
oAngieCtxt.Refresh(RefreshMode.KeepCurrentValues, rule);
}
oAngieCtxt.SubmitChanges();
}
return this.Json(new
{
msg = "Successful save.",
ruleId = rule.RuleId
});
}
You can't add an item to a list that you're enumerating over. Since you're looping over the rule.RuleConditions, you can't add to it inside the foreach loop. Instead, you can add to a temporary list and then add all items from that list to the rule.RuleConditions after the foreach.
var newRuleConditions = new List<RuleCondition>();
foreach (RuleCondition childItem in rule.RuleConditions)
{
if (childItem.RuleConditionId == 0)
{
oRuleCon = new RuleCondition();
oRuleCon.Points = childItem.Points;
oRuleCon.ConditionValue = childItem.ConditionValue;
oRuleCon.ToOperatorId = childItem.ToOperatorId;
oRuleCon.Sort = childItem.Sort;
//add to temporary list
newRuleConditions.Add(oRuleCon);
oAngieCtxt.RuleConditions.InsertOnSubmit(oRuleCon);
}
else
{
...
}
}
//add all new rule conditions
rule.RuleConditions.AddRange(newRuleConditions);
I am writing a single linked list in C#, could you please suggest to me if there any way to write a better remove method than the one I have:
using System;
class Node
{
public int data = int.MinValue;
public Node m_NextNode;
public Node(int data_in)
{
data = data_in;
}
public Node()
{
}
}
class LinkedList
{
private Node m_HeadNode;
public void InsertData(int data)
{
Node aCurrentNode = m_HeadNode;
if(m_HeadNode == null)
{
m_HeadNode = new Node();
m_HeadNode.data = data;
}
else
{
while(aCurrentNode.m_NextNode != null)
aCurrentNode = aCurrentNode.m_NextNode;
aCurrentNode.m_NextNode = new Node();
aCurrentNode.m_NextNode.data = data;
}
}
public void DisplayData()
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
Console.WriteLine("the value is {0}", aCurrentNode.data);
aCurrentNode = aCurrentNode.m_NextNode;
}
}
public void RemoveData(int data)
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
//if the data is present in head
//remove the head and reset the head
if (m_HeadNode.data == data)
{
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
}
else
{
//else save the previous node
Node previousNode = aCurrentNode;
if (aCurrentNode != null)
{
//store the current node
Node NextNode = aCurrentNode.m_NextNode;
if (NextNode != null)
{
//store the next node
Node tempNode = NextNode.m_NextNode;
if (NextNode.data == data)
{
previousNode.m_NextNode = tempNode;
NextNode = null;
}
}
aCurrentNode = aCurrentNode.m_NextNode;
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
LinkedList aLinkedList = new LinkedList();
aLinkedList.InsertData(10);
aLinkedList.InsertData(20);
aLinkedList.InsertData(30);
aLinkedList.InsertData(40);
aLinkedList.DisplayData();
aLinkedList.RemoveData(10);
aLinkedList.RemoveData(40);
aLinkedList.RemoveData(20);
aLinkedList.RemoveData(30);
aLinkedList.DisplayData();
Console.Read();
}
}
I would pull the 'if removing the head node' out of the while loop, and make the while loop simpler. Just keep track of the current and previous nodes, and switch the reference when you find the node to remove.
public void RemoveData(int data)
{
if (m_HeadNode == null)
return;
if (m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
else
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
break;
}
previous = current;
current = current.m_NextNode;
}
}
}
Is RemoveData supposed to remove one instance of that integer from the list, or all instances? The previous method removes just the first one, here's one that removes all of them.
public void RemoveAllData(int data)
{
while (m_HeadNode != null && m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
if(m_HeadNode != null)
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
// If we remove the current node, then we don't need to move
// forward in the list. The reference to previous.Next, below,
// will now point one element forward than it did before.
}
else
{
// Only move forward in the list if we actually need to,
// if we didn't remove an item.
previous = current;
}
current = previous.m_NextNode;
}
}
}
You have a line you do not need:
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
You don't need to set m_HeadNode to null before you set it to something else.
public bool RemoveNode(int data) {
Node prev = null;
for (Node node = head; node != null; node = node.next) {
if (node.data == data) {
if (prev == null) head = node.next;
else prev.next = node.next;
return true;
}
prev = node;
}
return false;
}
public void RemoveData(int data)
{
if(null == m_HeadNode) return;
if(m_HeadNode.data == data)
{
// remove first node
}
else
{
Node current = m_HeadNode;
while((null != current.m_NextNode) && (current.m_NextNode.data != data))
current = current.m_NextNode;
if(null != current.m_NextNode)
{
// do remove node (since this sounds like homework, I'll leave that to you)
}
}
}
with only one local variable.
There is a bug in you code, imagine you have list that has 3 elements with data = 5 and you want to remove 5, you codes stores the head in aCurrentNode and starts the loop. There the condition is true so you move the head to the next. but aCurrentNode is not updated so in the next iteration it's pointing to the previous Head and aCurrentNode.m_NextNod would be your current Head, Hence you got yourself in a never ending loop!
public void Remove(int data)
{
for(var cur = new Node {Next = Head}; cur.Next != null; cur = cur.Next)
{
if (cur.Next.Data != data) continue;
if (cur.Next == Head)
Head = Head.Next;
else
cur.Next = cur.Next.Next;
}
}
a trick to make you loop simpler is to start with a fake node that points to head. This way you don't need to place an If to check head differently, however you need an if to set the head. the other trick is to check for next nodes data. that way you don't need to keep a previous Node.
public SLElement Remove(int index)
{
SLElement prev = _root;
if (prev == null) return null;
SLElement curr = _root._next;
for (int i = 1; i < index; i++)
{
if (curr == null) return null;
prev = curr;
curr = curr._next;
}
prev._next = curr._next;
curr._next = null;
return curr;
}
This deletes the element with a specific index, not with a specific value.
To Make really simple. Please follow the link. Below is a code snippet to remove item from a single link list.
public void DeleteNode(int nodeIndex)
{
int indexCounter = 0;
Node TempNode = StartNode;
Node PreviousNode = null;
while (TempNode.AddressHolder != null)
{
if (indexCounter == nodeIndex)
{
PreviousNode.AddressHolder = TempNode.AddressHolder;
break;
}
indexCounter++;
PreviousNode = TempNode;
TempNode = TempNode.AddressHolder;
}
}
I've been working on a programmatic solution to edit the IPGrant table in IIS.
As it stands, I can View the IPGrant list Correctly, and CAN add to it.
However, I cannot remove or replace items in the IPGrant list.
MSDN and such recommend that you write (the values of the old list + the new value) to the List, however I'm finding I'm getting a HResult of "Cannot create file with that name, file already exists".
Adding to the list only works for me If I pass in the new value only.
After some reading:
http://www.west-wind.com/weblog/posts/59731.aspx
http://www.aspdev.org/articles/web.config/
http://www.codeproject.com/KB/security/iiswmi.aspx
http://www.codeproject.com/KB/security/iiswmi.aspx?msg=1739049
http://blogs.msdn.com/b/shawnfa/archive/0001/01/01/400749.aspx
http://msdn.microsoft.com/en-us/library/ms524322%28VS.90%29.aspx
http://www.eggheadcafe.com/software/aspnet/33215307/setting-ip-restrictions-in-iis-7.aspx
I'm finding that there is a compatability issue with IIS 7/6 and using the Metabase - in that one can only add to it, not remove.
Is there a more current method for IIS 7/7.5 that can be used (in c# please) to administrate the IPGrant table.
You can use Microsoft.Web.Administration, or AppCmd, or Javascript (COM - AHADMIN) to do that, here are a few examples on how to remove:
private static void Main() {
using(ServerManager serverManager = new ServerManager()) {
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection ipSecuritySection = config.GetSection("system.webServer/security/ipSecurity");
ConfigurationElementCollection ipSecurityCollection = ipSecuritySection.GetCollection();
ConfigurationElement addElement = FindElement(ipSecurityCollection, "add", "ipAddress", #"169.132.124.234", "subnetMask", #"255.255.255.255", "domainName", #"");
if (addElement == null) throw new InvalidOperationException("Element not found!");
ipSecurityCollection.Remove(addElement);
serverManager.CommitChanges();
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues) {
foreach (ConfigurationElement element in collection) {
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase)) {
bool matches = true;
for (int i = 0; i < keyValues.Length; i += 2) {
object o = element.GetAttributeValue(keyValues[i]);
string value = null;
if (o != null) {
value = o.ToString();
}
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase)) {
matches = false;
break;
}
}
if (matches) {
return element;
}
}
}
return null;
}
Using Javascript:
var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var ipSecuritySection = adminManager.GetAdminSection("system.webServer/security/ipSecurity", "MACHINE/WEBROOT/APPHOST");
var ipSecurityCollection = ipSecuritySection.Collection;
var addElementPos = FindElement(ipSecurityCollection, "add", ["ipAddress", "169.132.124.234","subnetMask", "255.255.255.255","domainName", ""]);
if (addElementPos == -1) throw "Element not found!";
ipSecurityCollection.DeleteElement(addElementPos);
adminManager.CommitChanges();
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}
And Finally AppCmd.exe:
appcmd.exe set config -section:system.webServer/security/ipSecurity /-"[ipAddress='169.132.124.234',subnetMask='255.255.255.255',domainName='']" /commit:apphost