Trying to bind DateTime.Now in gridview - asp.net

I am using Visual Web Developer Express 2013 and have created a gridview. When I update other values in the grid, I want txtDate to show the time the values were updated.
I set it up as an item template.
<asp:TemplateField HeaderText="txtDate" SortExpression="txtDate">
<itemtemplate><asp:label id="txtDate" runat="server"
text="<%# Bind DateTime.Now.ToString()%>"></asp:label>
</itemtemplate>
</asp:TemplateField>
When I use the above code without Bind - I get the current time displaying. I added Bind so that the current date would insert into the database and I get the following error;
Compiler Error Message: CS1026: ) expected
I'm trying to figure out the best way to insert the date when the values are updated. I also tried adding txtDate as a hidden field but that didn't work either.

Uses GetDate() function directly in the insert query, you don't need to show this to the user, because its just for logging purpose as far as I have understood what you want to do.

Related

Show date in UTC in ASP:GridView BoundField

I'm trying to use a GridView to show a DateTime value. So far I have been able to show the data using the format string that I want by using:
<asp:GridView ID="myGrid" ... >
<Columns>
<asp:BoundField DataField="myField" DataFormatString={0:MM/dd/yyyy hhmmss} ... />
...
</Columns>
...
</asp:GridView>
The problem I'm having now is that this is always being shown as local time. My users will be expecting it to always be shown as UTC, regardless of where they are. Is there some way I can force the GridView to show what the UTC time would be, instead of the local time?
For example, I have found out that in vb.net, to convert a string to a date I can tell it to use universal time with:
Dim myDateAsString as String = "03/31/2014 19:00"
Dim myDate as DateTime = DateTime.ParseExact(myDateAsString, "MM/dd/yyyy HH:mm", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AssumeUniversal)
I'm looking for something similar to the .AssumeUniversal part that I can use when I set up my GridView in asp.
I hope what I'm asking is clear. If not I can try to elaborate more, if someone let's me know what isn't clear.
UPDATE:
The DataSource for my GridView is a DataSet that is filled by a SELECT query that just pulls data from my database. Since the field I'm interested in here is a DateTime field in my database, I am assuming it will still be a DateTime when it gets assigned as the DataSource. Is that correct?
It looks to me like the only code related to filling the GridView is
myGrid.DatqaSource = mySQLObject.sel_from_table(vars)
myGrid.DataBind()
Where mySQLObject.sel_from_table(vars) will return a DataSet as described above. The answers so far have suggested that I need to change the data to UTC before sending it to the GridView - Where/how should that be done? Do I have to change it in my query somehow? Or in the DataSet before I assign it as the DataSource?
The grid view is merely a display mechanism. It'll display whatever value you pass it in the format you specified. If you want to change the value itself (Utc Date) then 2 options are:
Template Item where you can call an Eval option to compute Utc Date.
Change the value of myField server side so that the grid view can bind that. e.g. in your SQL query results.
Either ways, your server side code needs to convert the date into UTC (ToUniversalTime() or DateTime.UtcNow etc.) and send it across for display.
here is how you can do using TemplateField.
in your ASPX
<asp:TemplateField HeaderText="My Fields">
<ItemTemplate>
<asp:Label runat="server" text='<%# GetUtcFormattedDate((DateTime)Eval("myField")) %>' />
</ItemTemplate>
</asp:TemplateField>
In your code behind, you can have a static method
public static string GetUtcFormattedDate(DateTime date)
{
return date.ToUniversalTime().ToString(YOUR_DATE_FORMAT_STRING);
}
You could convert the time to UTC in your query to pull the data from the database.
In your select clause just use the below.
SELECT DATEADD (HH, 'Your UTC Offset', DateYouWantSelected)

Sorting a bound ASP.NET GridView on the Count of items in an Entity Framework navigation property

I have an ASP.NET page with a GridView control bound to an EntityDataSource (see simplified code below). The grid is showing a list of Parent items and includes a column to show the .Count of Children for this parent. I can get the grid to show the count properly, but I can't figure out what to use for the asp:TemplateField SortExpression value to be able to set the sort to the count of children.
Here is what my code looks like (simplified for clarity)...
<asp:EntityDataSource ID="edsParentList" runat="server"
ConnectionString="name=FooEntities"
DefaultContainerName="FooEntities"
EnableFlattening="False"
EntitySetName="Parents"
EntityTypeFilter="Parent"
Include="Children"
OrderBy="it.Name"
Where="(it.Name LIKE '%' + #ParentNameLike + '%')
>
<WhereParameters>
<asp:Parameter Name="ParentNameLike" Type="String" DefaultValue="_" />
</WhereParameters>
</asp:EntityDataSource>
<asp:GridView ID="grdParents" runat="server"
AllowPaging="True"
AllowSorting="True"
AutoGenerateColumns="False"
DataSourceID="edsParentList"
PageSize="20"
onpageindexchanged="grdParents_PageIndexChanged" onsorted="grdParents_Sorted" >
<Columns>
<asp:TemplateField HeaderText="Name" SortExpression="Name">
<ItemTemplate>
<%# Eval("Name") %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="BirthDate" HeaderText="Birth Date"
DataFormatString="{0:yyyy-MM-dd HH:mm}"
SortExpression = "BirthDate" />
<asp:TemplateField HeaderText="Children" SortExpression="Children.Count">
<ItemTemplate>
<asp:Label ID="lblChildCount" runat="server"
Text='<%# Eval("Children.Count") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
This displays the grid fine. However, when I click on the header of the Children column, this error is thrown:
'Count' is not a member of
'Transient.collection[FooEntities.Child(Nullable=True,DefaultValue=)]'.
To extract a property of a collection element, use a subquery to
iterate over the collection.
My question is: How do I enable sorting on the .Count() of a navigation property which consists of a collection of child objects?
Is there a way to specify this with SortExpression or do I have to break down and do all my paging and sorting manually? (Which I'd obviously prefer to avoid!)
In your position, since the entity classes are declared as partial, I would try creating a supplemental partial class code file for the Parent entity, and add a ChildCount read-only property. This property would reference the Children navigation property. I would then sort on that.
I am assuming, here, that an EntityDataSource can work with what I'll call derived properties on an entity. I have not tested this.
I have reproduced the error (in a simpler example) and I believe it is not possible to find any SortExpression that would perform a sorting on the children's count.
I have seen two important additional information:
The exception thrown when you click on the column header is an EntitySqlException
The last method in the stack trace which finally throws the exception is EntityDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)
ExecuteSelect is an abstract method of DataSourceView which is overriden by the various specific data source controls to perform the actual work to load data from the data store. In case of the EntityDataSource the corresponding view is the EntityDataSourceView and from the exception thrown - an EntitySqlException - I would conclude that ExecuteSelect builds the query using Entity SQL.
The argument DataSourceSelectArguments contains parameters defined in the EntityDateSource and also a SortExpression which is very likely just the sort expression you specified on the TemplateField. Those are used to compose the final query in Entity SQL.
I would assume that the SortExpression is just passed as an ORDER BY clause in the Entity SQL statement. This would look like:
ORDER BY Children.Count
But this is invalid Entity SQL. You can use dotted paths for a navigation reference, but you cannot use any "LINQ-like" methods or properties (like Count) of a navigation collection in Entity SQL.
It is possible to write a valid Entity SQL so sort by the children's count. According to this example (search for "Order By - Related Entities" in the file) a correct Entity SQL statement would be:
"SELECT VALUE p2.p
FROM (SELECT p, ANYELEMENT(SELECT VALUE Count(c.ChildId) FROM p.Children AS c)
AS childCount
FROM Parents AS p)
AS p2
ORDER BY p2.childCount"
(This is so hard to read that I even don't know how to indent the code semantically correct.)
I think this ANYELEMENT(SELECT... construct is the "subquery" the exception is talking about and wants to have in order to count the elements of the children collection.
Obviously you can't pass p2.childCount into SortExpression without the whole subquery which defines p2.
My conclusion: There is no hope to find a working SortExpression for the children count.
Maybe there is a way without using the SortExpression - for example by catching a click event on the header and then building the complete query manually in the event handler, but I do not really know, if and how it's possible.
Why do consumers of the EntityDataSource and GridView have to figure out that themselves? Did you anywhere see documented: "When the data source is of type EntityDataSource the SortExpression of a TemplateField in a GridView must be a valid Entity SQL ORDER BY clause." I didn't. Just something like: "The SortExpression is an expression for sorting."
Unfortunately, because it is nowhere clearly said what happens with the SortExpression, what is the correct syntax and what kind of expressions are supported or not, this answer is more a guess than an answer.

ASP.NET DetailView InsertItemTemplate

I have a InsertItemTemplate defined in my DeatilView control. Within this template I have a number of fields that the user fills and a number of fields that are filled automatically and the user cannot change them. These values are coming from an object stored in session.
Code looks like this: (I only mention necessary parts, if you need anything more let me know)
<asp:DetailView ... DataSourceID="MyDataSource" ...>
<Fields>
...
<InsertItemTemplate>
// These are the fields filled by the system
<asp:Label ... Text='<%# some value from session object %>' />
<asp:Label ... Text='<%# some value from session object %>' />
// some textboxes here that user fills,
//they use Bind("some data source value here") to send their data to database
...
</InsertItemTemplate>
...
</Fields>
</asp:DetailView>
Now the problem is where I need to actually insert values into database.
Textbox values are sent just alright, but since I haven't bound label values they are not sent to DataSource. So I'm asking how to do this?
An alternative I found was to pass a DefaultValue to DataSet's
respective InsertParameter but I don't know how to fill that area to
get it's value from Session.
Another alternative is to set Parameter's value (not default value)
to be taken from Session, which is possible but this only support
values that are directly within Session, and I'm passing the value of
a property inside an object that's stored in Session. Is there a
way to get this fixed, other than storing values inside Session
directly.
What type of DataSource are you using? I need to know it, because there is few ways to obtain parameters from session depending on type of datasource.
detailView_ItemInserting(object sender, DetailsViewInsertEventArgs e) is called just before inserting the data, you can use detailView.FindControl method in this event to get access to Label controls.

Connecting a gridview to multiple tables linqdatasource

I'm just playing with some linq and asp.net - absolute beginner so I'm not even sure exactly how to ask my question.
Anyway, I have a MSSQL database with asp membership info in it. For various reasons (mainly to store profile info in clear columns instead of all in one) I'm using a custom profile provider so my profile information is spread across a few tables in my database.
I have the normal aspnet_membership and aspnet_profle, but then I also have a tblUserProfile table, in which I store a bunch of user profile information like first name, phone number etc. The tblUserProfile also has a companyID in it, referring to a seperate table with a list of companies in it.
All tables have a GUID UserId as their key.
I created a datamodel diagram that contains all the tables I'm using and it shows the keys linking up etc properly.
So now I have a gridview that uses a LinqDataSource that is connected to the aspnet_membership table. This bit so far works well, I'm able to display all the info in the aspnet_membership table. I also figured out how to show the company a user is in like this:
<asp:TemplateField HeaderText="Company" SortExpression="tblUserProfile.Company.CompanyName">
<ItemTemplate>
<%#Eval("tblUserProfile.Company.CompanyName") %>
</ItemTemplate>
What I can't figure out is how to make changes to this save to the database. If I change direct fields in aspnet_membership table, they update properly.
I created a dropdown showing all available companies, you can select the company to change directly in the grid, but when I try to update it reverts back to the original value.
<asp:TemplateField HeaderText="Company" SortExpression="tblUserProfile.Company.CompanyName">
<ItemTemplate>
<%#Eval("tblUserProfile.Company.CompanyName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="CompanyDropDownList"
DataSourceID="CompanyDataSource"
DataValueField="Id"
DataTextField="CompanyName"
SelectedValue='<%#Bind("tblUserProfile.CompanyID") %>'
runat="server">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
I'm not sure if it's because my datasource is connecting to one table (aspnet_membership) but the value I'm trying to change is in tblUserProfile. It seems that I can retrieve/display values from the other tables connected via foreign keys, but can I also update values in those tables?
Sorry for a long winded question, but I'm pretty new to this so aren't sure exactly where the problems are otherwise I'd be more specific.
Thanks for any pointers
It sounds like you are trying to use the automatic updating provided by the LinqDataSource but as you point out, that doesn't work properly with joined data. That is a limitation of the automatic updating. You can however subscribe to one of the OnUpdating events and write some code to handle the additional updating. How exactly that should be written depends on the names of your key values, etc. but there should be some information about it on this site and elsewhere.
You can create a custom databound control to edit the sub objects
public class CompositeBoundField : BoundField
{
protected override object GetValue(Control controlContainer)
{
object item = DataBinder.GetDataItem(controlContainer);
return DataBinder.Eval(item, this.DataField);
}
}
And then use this in a page like so:
<cc:CompositeBoundField DataField="aspnet_Membership.Email" HeaderText="Email"/>
Then add this to the web.config:
<pages>
<controls>
<add assembly="App_Code" namespace="CustomControls" tagPrefix="cc"/>
</controls>
Let me know if this helps by giving me an up-check. It is possible to create other bound fields for checkbox or other types. This may have been the original author/source for this method:
http://iridescence.no/post/FixingBoundFieldSupportforCompositeObjects.aspx

ASP.NET Drop Down List error with null values in SqlDataSource

I have a drop down list on a form view which are both bound to different data sources.
When trying to run the program I am getting 'ddlFieldName' has a SelectedValue which is invalid because it does not exist in the list of items. Parameter name: value.
I think it is because the field associated with the drop down list contains a null value which isnt in the referencing table. I have tried to work round this by adding an empty item in the list but it doesnt seem to be working:
<asp:DropDownList ID="ddlAgency" runat="server"
DataSourceID="dsAgency" DataTextField="Agency"
DataValueField="AgencyID" SelectedValue='<%# Bind("Agency") %>' >
<asp:ListItem></asp:ListItem></asp:DropDownList>
Can anyone suggest a way round this?
Thanks
anD666
Try adding AppendDataBoundItems="true" to the DropDownList as one if its properties. See http://weblogs.asp.net/scottgu/archive/2006/01/29/436804.aspx
One workaround could be.
Try to assign Selected value in code behind. There you can check for null value easily.

Resources