I have a website using dynamic data and linq to sql. This website runs 3 'subsites' and has a list of categories with a many to many relationship.
I have 3 tables and hence 3 objects in my dbml; Website, Categories, and CategoriesToWebsites
What I am trying to do is create a field template such that on my Categories/Edit.aspx page I can edit a category and specify which website the category belongs in.
The field template is CategoriesToWebsites_Edit.ascx, which is basically a checkbox list bound to the list of websites.
Code below:
public partial class CategoriesToWebsitesEdit : FieldTemplateUserControl
{
protected override void OnLoad(EventArgs e)
{
var dataSource = (LinqDataSource)this.FindDataSourceControl();
dataSource.Inserting += OnInserting;
dataSource.Updating += OnUpdating;
}
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
//check if website category already exists
var categoryToWebsite = oldCategory.CategoriesToWebsites.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//website category exists
if (categoryToWebsite != null)
{
// check if selected for removal, remove
if (!listItem.Selected)
{
newCategory.CategoriesToWebsites.Remove(categoryToWebsite);
}
}
//we want to insert
if (listItem.Selected)
{
//website category does not exist, add
if (categoryToWebsite == null)
{
//add selected website if not already exists
newCategory.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
}
}
private void OnInserting(object sender, LinqDataSourceInsertEventArgs e)
{
var category = (Category)e.NewObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
if(!listItem.Selected)
continue;
category.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
protected override void OnDataBinding(EventArgs e)
{
var websiteRepository = new WebsiteRepository();
var websites = websiteRepository.GetAll();
var websiteCategories = (IEnumerable<CategoriesToWebsite>)FieldValue;
foreach(var website in websites)
{
var currentWebsite = website;
var listItem = new ListItem(website.Name, website.Id.ToString())
{
Selected = websiteCategories == null ? false : websiteCategories.Any(w => w.WebsiteId == currentWebsite.Id)
};
WebsiteList.Items.Add(listItem);
}
}
}
When I go to Categories/Insert.aspx to create a new category, it runs through the OnInserting code fine and saves it to db just fine, everything seems to be working here.
On Categories/Edit.aspx it goes through the code just as I expect, but does not seem to save anything.
What am I missing? - I'm not too familiar with Dynamic Data Field Templates so any guidance will be much appreciated
Apparently I was going about this slightly wrong. I was simply updating the object in the linq data source, which wasn't being saved. So instead I go straight to the repository:
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
var repository = new Repository<CategoriesToWebsite>();
var ctw = repository.GetAll().Where(x => x.CategoryId == newCategory.Id);
foreach (var listItem in WebsiteList.Items.Cast<ListItem>())
{
var current = ctw.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//current categoriesToWebsite exists
if (current != null)
{
//if not selected, remove
if (!listItem.Selected)
repository.Delete(current);
}
//does not exist
else
{
//if selected, add
if (listItem.Selected)
repository.Save(new CategoriesToWebsite()
{
CategoryId = newCategory.Id,
WebsiteId = Convert.ToInt32(listItem.Value)
}
);
}
}
UnitOfWork.Current.SubmitChanges();
}
I'm not sure if this is the proper way to do this since the field template here is doing some updating directly to the db. But it works.