Updating ContentBlock pulled from pageManager.LoadControl(). Sitefinity 5 - c#

Asked this on the forums as well, but no luck as of yet. What I need to do is set the HTML content of each content block on a given page. It seems that I can set the html value okay, but saving it does not update the actual page.
I'm wondering if it's because there needs to be some sort of save call on the control. There doesn't seem to be any methods available for such an action.
foreach (var c in duplicated.Page.Controls)
{
// go through the properties, se the ID to grab the right text
foreach (var p in c.Properties)
{
if (p.Name == "ID")
{
var content = pageContent.Where(content_pair => content_pair.Key == p.Value).SingleOrDefault();
var control = pageManager.LoadControl(c);
if (control is ContentBlock)
{
var contentBlock = pageManager.LoadControl(c) as ContentBlock;
contentBlock.Html = content.Value;
}
}
}
}
pageManager.SaveChanges(); */
WorkflowManager.MessageWorkflow(duplicated.Id, typeof(PageNode), null, "Publish", false, bag);

The following code may help you achieve what you need.
It will first get the page by its title (I am looking for a page by the title "duplicated" as it's implied by your code).
It generates a new draft of the current page, then go over its controls.
Controls which are detected as content blocks are then iterated in a foreach loop.
As written in the comment inside the foreach loop, you may detect controls by their explicit ID (by the property named "ID") or by their related shared content block (by the property named "SharedContentID") or any other condition (or ignore this condition altogether, which would result in updating all the controls n the page.
Once we have a control to update at hand, you can set its new value depending on the localization settings of your project.
After that the draft is saved and published and optionally a new version is created for it.
PageManager pageManager = PageManager.GetManager();
VersionManager vmanager = VersionManager.GetManager();
PageNode duplicated = pageManager.GetPageNodes().FirstOrDefault(p => p.Title == "duplicate");
if (duplicated != null)
{
var draft = pageManager.EditPage(duplicated.Page.Id, true);
string contentBlockTypeName = typeof(ContentBlock).FullName;
PageDraftControl[] contentBlocks = draft.Controls.Where(contentBlock => contentBlock.ObjectType == contentBlockTypeName).ToArray();
foreach (PageDraftControl contentBlock in contentBlocks)
{
Guid contentBlockId = contentBlock.Id;
//User "SharedContentID" if you are looking up controls which are linked to a shared content block of a specific ID.
//If you you are trying to locate a specific control by its own ID, use the explicit "ID" property instead of "SharedCotentID"
if (contentBlock.Properties.Where(prop => prop.Name == "SharedContentID" && prop.Value.ToString() == contentItemIdstr).FirstOrDefault() != null)
{
ControlProperty htmlProperty = contentBlock.Properties.Where(prop => prop.Control.Id == contentBlockId && prop.Name == "Html").FirstOrDefault();
if (htmlProperty != null)
{
if (AppSettings.CurrentSettings.Multilingual)
{
htmlProperty.GetString("MultilingualValue").SetString(CultureInfo.CurrentUICulture, "New Value");
}
else
{
htmlProperty.Value = "New Value";
}
}
}
}
draft = pageManager.SavePageDraft(draft);
draft.ParentPage.LockedBy = Guid.Empty;
pageManager.PublishPageDraft(draft);
pageManager.DeletePageTempDrafts(draft.ParentPage);
//Use the 2 next lines to create a new version of your page, if you wish.
//Otherwise the content will be updated on the current page version.
vmanager.CreateVersion(draft, draft.ParentPage.Id, true);
vmanager.SaveChanges();
pageManager.SaveChanges();
}
I hope this code helps.
Alon.

Related

Indexing content that is attached to some page

I have this requirment to only index that data, for searching, which is being used in some page. For example if I upload a document it shouldn't be available for search until I use it in some page. I found out this code online
ContentIndexer.Instance.Conventions.ForInstancesOf().ShouldIndex(x =>
{
var contentRepository =
EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance();
var contentSoftLinkRepository =
EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance();
var softLinks = contentSoftLinkRepository.Load(x.ContentLink, true);
try
{
foreach (var softLink in softLinks)
{
if (softLink.SoftLinkType == ReferenceType.ExternalReference ||
softLink.SoftLinkType == ReferenceType.ImageReference)
{
var content =
contentRepository.Get(softLink.OwnerContentLink);
if (!ContentIndexer.Instance.Conventions.ShouldIndexConvention.ShouldIndex(content).Value) // don't index referenced file if content is marked as not indexed
{
continue;
}
// only index if content is published
var publicationStatus =
content.PublishedInLanguage()[softLink.OwnerLanguage.Name];
if (publicationStatus != null &&
(publicationStatus.StartPublish == null ||
publicationStatus.StartPublish < DateTime.Now) &&
(publicationStatus.StopPublish == null ||
DateTime.Now < publicationStatus.StopPublish))
{
return true;
}
}
}
}
catch
{
// ooops something went wrong. Better not index this one ;-)
}
return false;
});
This works when I attach softlinks. But lets say a page has a property called Content type and when I add something in there, lets say a block which has softlinks to that document, it doesn't work. I am stuck in there. Any hints?
Do you have a wildcard * host configured on any of your sites?
Check Admin > Manage websites and go through all sites to see if there is a * configured.
Having a wildcard tells Episerver Find to index standalone content (i.e. globalassets) using the site primary URL that contains the wildcard, regardless of it being referenced. If you don't have a wildcard configured, Episerver Find can't index content that are NOT referenced (i.e. globalassets) because it cannot generate a public URL for it. Global assets that are referenced will be indexed using the domain of the site that references it. Hope this helps.

Creating sitecore item programmatically in specific language

I am trying to create a sitecore item programmatically. All working good. But the item I am creating from is in language "EN-GB" but new item created is in language "EN". Is there a way I can set the language value while creating an item.
var currentDatabase = Sitecore.Configuration.Factory.GetDatabase(selectedItem.Database.Name);
if (currentDatabase != null)
{
var rootItem = currentDatabase.GetItem(RootItemPath);
if (rootItem != null)
{
//Create new item
var item = rootItem.Add(selectedItem.Name, CommunityProjectTemplateId);
if (item != null)
{
item.Fields.ReadAll();
item.Editing.BeginEdit();
try
{
//Add values for the fields
item.Fields["Overview Body Content"].Value = selectedItem.GetStringField("ProjectOverview");
}
catch (Exception)
{
item.Editing.EndEdit();
}
}
}
}
You need to switch the context language before you retrieve the root item.
using (new LanguageSwitcher("en-gb"))
{
var rootItem = currentDatabase.GetItem(RootItemPath);
var item = rootItem.Add(selectedItem.Name, CommunityProjectTemplateId);
// Do your editing on item here...
}
If you are trying to add an item in en-GB then make sure that the "Root Item" that you get is in en-GB by doing this.
Language language;
Language.TryParse("en-GB", out language);
var rootItem = currentDatabase.GetItem(RootItemID, language);
After that if you try to add an item it will be in that language.
Using the Language Switcher is a great idea as well but be careful when changing language context.
You can use the following code before creating an item
var language = Sitecore.Globalization.Language.Parse( "en-GB" );
Sitecore.Context.SetLanguage( language, true );
The last line will set the context language to en-GB. Then the item will be created with that language version.

Why is my Session["value"] not persisting across views (asp.net mvc)

I am electing to do session to store a value that I will need to call and update throughout a handful of controllers and views. I know it is possible to do something like this with a BaseViewModel.cs, or something less session-y, but I am trying to see how Session can possibly solve my needs. That out of the way, here is what I am doing:
Flow
I have a partial view that is rendered on my _layout page like so:
#Html.Action("OrgSwitch", new { controller = "Common", area = "InkScroll" })
This is a drop down list containing a logged in users organizations. It hits a CommonController that takes care of things like rendering model-bound logic on layout pages. In the CommonController I have this view and a postback, like so:
[ChildActionOnly]
public ViewResult OrgSwitch()
{
var userOrgs = new List<SelectListItem>();
var user = Ctx.Users.FirstOrDefault(x => x.UserName == User.Identity.Name);
int key = 0;
if (user.Organizations.Count > 0)
{
TempData["HasOrgs"] = true;
foreach (var org in user.Organizations)
{
if (Session["SelectedOrgKey"] == null)
{
//currently setting selected by primary org id
//todo: set selected to tempdata selectedOrgId if there is one.
userOrgs.Add(org.OrganizationId.ToString() == user.PrimaryOrgId
? new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = true }
: new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = false });
}
else
{
key = Convert.ToInt32(Session["SelectedOrgKey"]);
userOrgs.Add(org.OrganizationId == key
? new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = true }
: new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = false });
}
}
ViewBag.UserOrgs = userOrgs.OrderBy(x => x.Text);
}
else
{
ViewBag.UserOrgs = userOrgs;
TempData["HasOrgs"] = false;
}
Session["SelectedOrgKey"] = key;
return View();
}
[HttpPost]
public RedirectToRouteResult OrgSwitch(string UserOrgs)
{
Session["SelectedOrgKey"] = UserOrgs;
return RedirectToAction("Index", "Recruiter", new { orgId = UserOrgs, area = "InkScroll" });
}
This more or less on initial load will render the drop down list and default it to the users primary org. If they select something and post back that selection, it will display the selected one by default on subsequent pages.
attempt and failure
I am trying various ways of utilizing the Session value. One area in a viewresult:
[ChildActionOnly]
public ViewResult StaffList()
{
var user = Ctx.Users.FirstOrDefault(x => x.UserName == User.Identity.Name);
var model = new List<StaffListViewModel>();
int key = Convert.ToInt32(Session["SelectedOrgKey"]);
var org = user.Organizations.FirstOrDefault(x => x.OrganizationId == key);
if (org.RegisteredMembers != null)
{
foreach (var req in org.RegisteredMembers)
{
model.Add(new StaffListViewModel
{
UserName = req.UserName,
Name = (req.FirstName ?? "") + " " + (req.LastName ?? ""),
ImageLocation = req.ImageLocation
});
}
}
Session["SelectedOrgKey"] = key;
return View(model);
}
in here 'key' is coming up empty.
Another try is putting it in the layout cshtml file like so:
<li><a href="#Url.Action("Staff", "Recruiter", new {area="",
orgId = Convert.ToInt32(Session["SelectedOrgId"])})">Staff</a></li>
in this one if I hover over the link, the orgId is always equal to 0. Am I messing this up somewhere? Really, I need to have this SelectedOrgId available to any page on the application.
An answer for posterity sake:
The code in the question DOES work. The way I am setting and calling session in asp.net mvc works fine. If you have arrived here in a vain search to get session working, then keep looking I guess. The issue I was have related to my control flow and the parameter i was passing in. Once I removed the 'orgId' from the parameters above, I refactored the if/else stuff to just look at session. So the issue was that somewhere in the app I am working on, orgId was not being changed from '0'. Anyway, I am an idiot, but at least I can give you a quick overview of what the hell Session is in asp.net mvc and how easy it is to use:
Setting up app to use session
Session is defaulted to be in process with a timeout of 20 minutes. If you feel like something is overwriting that default you can set it explicitly in your web.config (root web.config on a standard asp.net mvc app):
<system.web>
<sessionState mode="InProc" timeout="60"></sessionState>
...other stuff..
</system.web>
I set my timeout above to 60 minutes since I wanted it to stay around a little longer. Standard is 20.
Setting a session variable
Pretty damn simple. Do this:
Session["MyStringVariable"] = "Some value I want to keep around";
Session["MyIntegerVariable"] = 42;
Retrieving the session variable
again, pretty simple, you just need to pay attention to casting/converting the variable to what suits you.
var localVar = Session["MyStringVariable"].ToString();
var anotherLocalVar = Convert.ToInt32(Session["MyIntegerVariable"] = 42);
So, yeah, I was doing it right, but due to other complexities in my code above, I blamed the big bad Session and not my brain.
Hope this helps someone! (And if I have the above info wrong, please let me know and I will update!).

UI Automation not working for DataGridView

After trying out several solutions, I am in desperate need for help.
I tried several approaches, before finally copying and still being stuck with the solution from Getting full contents of a Datagrid using UIAutomation.
Let's talk code, please consider the comments:
// Get Process ID for desired window handle
uint processID = 0;
GetWindowThreadProcessId(hwnd, out processID);
var desktop = AutomationElement.RootElement;
// Find AutomationElement for the App's window
var bw = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ProcessIdProperty, (int)processID));
// Find the DataGridView in question
var datagrid = bw.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));
// Find all rows from the DataGridView
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));
// Badumm Tzzz: loginLines has 0 items, foreach is therefore not executed once
foreach (AutomationElement loginLine in loginLines)
{
var loginLinesDetails = loginLine.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));
for (var i = 0; i < loginLinesDetails.Count; i++)
{
var cacheRequest = new CacheRequest
{
AutomationElementMode = AutomationElementMode.None,
TreeFilter = Automation.RawViewCondition
};
cacheRequest.Add(AutomationElement.NameProperty);
cacheRequest.Add(AutomationElement.AutomationIdProperty);
cacheRequest.Push();
var targetText = loginLinesDetails[i].FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "TextBlock"));
cacheRequest.Pop();
var myString = targetText.Cached.Name;
}
}
I can neither fetch a GridPattern, nor a TablePattern instance from datagrid, both results in an exception:
GridPattern gridPattern = null;
try
{
gridPattern = datagrid.GetCurrentPattern(GridPattern.Pattern) as GridPattern;
}
catch (InvalidOperationException ex)
{
// It fails!
}
TablePattern tablePattern = null;
try
{
tablePattern = datagrid.GetCurrentPattern(TablePattern.Pattern) as TablePattern;
}
catch (InvalidOperationException ex)
{
// It fails!
}
The rows were added to the DataGridView beforehand, like this:
dgvControlProperties.Rows.Add(new object[] { false, "Some Text", "Some other text" });
I am compiling to .Net Framework 4.5. Tried both regular user rights and elevated admin rights for the UI Automation client, both yielded the same results described here.
Why does the DataGridView return 0 rows?
Why can't I get one of the patterns?
Kudos for helping me out!
Update:
James help didn't to the trick for me. The following code tough returns all rows (including the headers):
var rows = dataGrid.FindAll(TreeScope.Children, PropertyCondition.TrueCondition);
Header cells can then be identified by their ControlType of ControlType.Header.
The code that you are copying is flawed. I just tested this scenario with an adaptation of this sample program factoring in your code above, and it works.
The key difference is that the code above is using TreeScope.Children to grab the datagrid element. This option only grabs immediate children of the parent, so if your datagrid is nested it's not going to work. Change it to use TreeScope.Descendants, and it should work as expected.
var datagrid = bw.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));
Here is a link to how the various Treescope options behave. Also, I don't know how your binding the rows to the grid, but I did it like this in my test scenario and it worked flawlessly.
Hopefully this helps.
public class DataObject
{
public string FieldA { get; set; }
public string FieldB { get; set; }
public string FieldC { get; set; }
}
List<DataObject> items = new List<DataObject>();
items.Add(new DataObject() {FieldA="foobar",FieldB="foobar",FieldC="foobar"});
items.Add(new DataObject() { FieldA = "foobar", FieldB = "foobar", FieldC = "foobar" });
items.Add(new DataObject() { FieldA = "foobar", FieldB = "foobar", FieldC = "foobar" });
dg.ItemsSource = items;
Your code looks fine though this could be a focus issue.
Even though you are getting a reference to these automation element objects you should set focus on them (using the aptly named SetFocus method) before using them.
Try:
var desktop = AutomationElement.RootElement;
desktop.SetFocus();
// Find AutomationElement for the App's window
var bw = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ProcessIdProperty, (int)processID));
and if that does not work try explicitly focusing on the dataGrid prior to calling "FindAll" on it i.e.
datagrid.SetFocus()
Why does the DataGridView return 0 rows?
The DataGridViewRows have a ControlType of ControlType.Custom. So I modified the line
// Find all rows from the DataGridView
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));
To
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));
That gets you all the rows within the DataGridView. But your code has that within the loop.
What pattern is supported by DataGridView (not DataGrid)?
LegacyIAccessiblePattern. Try this-
LegacyIAccessiblePattern legacyPattern = null;
try
{
legacyPattern = datagrid.GetCurrentPattern(LegacyIAccessiblePattern.Pattern) as LegacyIAccessiblePattern;
}
catch (InvalidOperationException ex)
{
// It passes!
}
As I commented on #James answer, there is no support for UIA for DataGridView (again, not DataGrid).
If you search in google with terms: "UI Automation DataGridView" the first result has an incomplete answer. Mike replies with what provider class (Obviously one that extends DataGridView)to create within the source, unfortunately I have no clue as to how to make UIA load that class a provider. If anyone can shed some clues, Phil and I will be extremely pleased!
EDIT
Your DataGridView should implement the interfaces in that link above. Once you do that the ControlType of Row will be ControlType.DataItem instead of ControlType.Custom. You can then use it how you'd use a DataGrid.
EDIT
This is what I ended up doing -
Creating a Custom DataGridView like below. Your datagridview could subclass this too. That will make it support ValuePattern and SelectionItemPattern.
public class CommonDataGridView : System.Windows.Forms.DataGridView,
IRawElementProviderFragmentRoot,
IGridProvider,
ISelectionProvider
{.. }
The complete code can be found # this msdn link.
Once I did that, I played a bit with visualUIVerify source. Here is how I can access the gridview's cell and change the value. Also, make note of the commented code. I didn't need that. It allows you to iterate through rows and cells.
private void _automationElementTree_SelectedNodeChanged(object sender, EventArgs e)
{
//selected currentTestTypeRootNode has been changed so notify change to AutomationTests Control
AutomationElementTreeNode selectedNode = _automationElementTree.SelectedNode;
AutomationElement selectedElement = null;
if (selectedNode != null)
{
selectedElement = selectedNode.AutomationElement;
if (selectedElement.Current.ClassName.Equals("AutomatedDataGrid.CommonDataGridViewCell"))
{
if(selectedElement.Current.Name.Equals("Tej")) //Current Value
{
var valuePattern = selectedElement.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
valuePattern.SetValue("Jet");
}
//Useful ways to get patterns and values
//System.Windows.Automation.SelectionItemPattern pattern = selectedElement.GetCurrentPattern(System.Windows.Automation.SelectionItemPattern.Pattern) as System.Windows.Automation.SelectionItemPattern;
//var row = pattern.Current.SelectionContainer.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewRow", PropertyConditionFlags.IgnoreCase));
//var cells = row.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewCell", PropertyConditionFlags.IgnoreCase));
//foreach (AutomationElement cell in cells)
//{
// Console.WriteLine("**** Printing Cell Value **** " + cell.Current.Name);
// if(cell.Current.Name.Equals("Tej")) //current name
// {
// var valuePattern = cell.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
// valuePattern.SetValue("Suraj");
// }
//}
//Select Row
//pattern.Select();
//Get All Rows
//var arrayOfRows = pattern.Current.SelectionContainer.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewRow", PropertyConditionFlags.IgnoreCase));
//get cells
//foreach (AutomationElement row in arrayOfRows)
//{
// var cell = row.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewCell", PropertyConditionFlags.IgnoreCase));
// var gridItemPattern = cell.GetCurrentPattern(GridItemPattern.Pattern) as GridItemPattern;
// // Row number.
// Console.WriteLine("**** Printing Row Number **** " + gridItemPattern.Current.Row);
// //Cell Automation ID
// Console.WriteLine("**** Printing Cell AutomationID **** " + cell.Current.AutomationId);
// //Cell Class Name
// Console.WriteLine("**** Printing Cell ClassName **** " + cell.Current.ClassName);
// //Cell Name
// Console.WriteLine("**** Printing Cell AutomationID **** " + cell.Current.Name);
//}
}
}
_automationTests.SelectedElement = selectedElement;
_automationElementPropertyGrid.AutomationElement = selectedElement;
}
Hopefully this helps.
I run into this problem too, after researching, i figured out that you can only access data grid view with LegacyIAccessible. However, .NET does not support this. So, here are the steps:
there are 2 versions of UIA: managed version and unmanaged version (native code). In some cases, the unmanaged version can do what the managed version can't.
=> as said here, using tblimp.exe (go along with Windows SDK) to generate a COM wrapper around the unmanaged UIA API, so we can call from C#.
I have done it here
we can use this to access DataGridView now but with very limited data, you can use Inspect.exe to see.
The code is:
using InteropUIA = interop.UIAutomationCore;
if (senderElement.Current.ControlType.Equals(ControlType.Custom))
{
var automation = new InteropUIA.CUIAutomation();
var element = automation.GetFocusedElement();
var pattern = (InteropUIA.IUIAutomationLegacyIAccessiblePattern)element.GetCurrentPattern(10018);
Logger.Info(string.Format("{0}: {1} - Selected", pattern.CurrentName, pattern.CurrentValue));
}

Repetitive tasks on multiple pages?

Using C# with ASP.NET on an Intranet website. I've got multiple "Admin" pages where I'm checking fields to make sure a date is present, checking fields to make sure the Username is present and filling in those fields if they were left blank. On all of these pages, there exists fields with identical names. The block of code I'm using in the code-behind is below:
//If the User fields are empty, set them to the current user
string ActiveUser = System.Web.HttpContext.Current.User.Identity.Name;
string LoginID = ActiveUser.Right(6);
var txtLoadedBy_chk = string.IsNullOrEmpty(str5);
if ((txtLoadedBy_chk == true))
{
str5 = LoginID;
}
var txtUpdatedBy_chk = string.IsNullOrEmpty(str7);
if ((txtUpdatedBy_chk == true))
{
str7 = LoginID;
}
var txtFlgUpdatedBy_chk = string.IsNullOrEmpty(str9);
if ((txtFlgUpdatedBy_chk == true))
{
str9 = LoginID;
}
// If the date fields are NULL, set them to today's date
var txtLoadedOn_chk2 = string.IsNullOrEmpty(str6);
if ((txtLoadedOn_chk2 == true))
{
str6 = DateTime.Today.ToString();
}
var txtUpdatedOn_chk2 = string.IsNullOrEmpty(str8);
if ((txtUpdatedOn_chk2 == true))
{
str8 = DateTime.Today.ToString();
}
var txtFlgUpdatedOn_chk2 = string.IsNullOrEmpty(str10);
if ((txtFlgUpdatedOn_chk2 == true))
{
str10 = DateTime.Today.ToString();
}
// Check to make sure the dates entered are valid. If not, let the user know and
// then exit out of the code so the record is not saved
var txtLoadedOn_chk = DateTimeHelpers.IsValidSqlDateTimeNative(str6);
var txtUpdatedOn_chk = DateTimeHelpers.IsValidSqlDateTimeNative(str8);
var txtFlgUpdatedOn_chk = DateTimeHelpers.IsValidSqlDateTimeNative(str10);
if ((txtLoadedOn_chk == false) || (txtUpdatedOn_chk == false) || (txtFlgUpdatedOn_chk == false))
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "ch", "<script>alert('WARNING !! One of your date fields is invalid')</script>");
return;
}
I'm thinking that since I do the EXACT same checks on all of these forms, I should be able to put this block of code somewhere and just reference it, instead of putting it in every form. How would I go about doing that? If I put it in a separate page or CS file, how will it know which form is calling it so it reads the proper fields? If you can provide some sample code, that would be a huge help. TIA!
Oh, and DateTimeHelpers is a class I created, in case you're wondering.
EDIT: I just want to be clear on something; this code is in the code-behind and is called when the user presses the "Save" button. It's just verifying the data before it tries to write it to the SQL Server table.
What you want to do here is create a user control. You can add one of those to your project with the "New File" stuff Visual Studio provides. I will call that user control Fields.ascx in this answer.
The code in your answer goes in the code-behind for that user control (Fields.ascx.cs). The form elements that you have on every page go in Fields.ascx.
Once you do that, you reference the user control at the top of your page like this:
<%# Register TagPrefix="user2174085" TagName="MyFields" Src="~/Path/To/Fields.ascx" %>
And then you add the fields to your page in the right place with the following code:
<user2174085:MyFields runat="server" />
In the <%# Register %> portion, you can make the TagPrefix and TagName pretty much anything you want, just make sure they match when you use the control.
You could always write a public method in a cs file and pass your controls as reference variables. Here is a quick example of what that could look like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
namespace mol_intranet
{
public class ClassTesting
{
//pass the fields to be checked/updated here as ref variables
public void checkFields(ref TextBox loadedby, ref TextBox updatedby)
{
string ActiveUser = System.Web.HttpContext.Current.User.Identity.Name;
string LoginID = ActiveUser.Right(6);
var txtLoadedBy_chk = string.IsNullOrEmpty(loadedby.Text);
if ((txtLoadedBy_chk == true))
{
loadedby.Text = LoginID;
}
var txtUpdatedBy_chk = string.IsNullOrEmpty(updatedby.Text);
if ((txtUpdatedBy_chk == true))
{
updatedby.Text = LoginID;
}
}
}
}
Then just call the method in your code and pass your controls:
ClassTesting t = new ClassTesting();
t.checkFields(txtLoadedBy, txtUpdatedBy);
Hope this helps.

Categories