ASP.NET DetailView InsertItemTemplate - asp.net

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.

Related

How to "bind" invisible and unbound field in ASPXGridView EditFromTemplate?

I have an ASPxGridView with edit form template. DataSource for this grid is EntityServerModeSource which is a read-only data source. I use this combination because it delegates filtering and sorting to database server.
For simplicity I will present simplified scenario.
My EntityServerModeSource return rows with fields A,B and C.
What I do for update is following. In EditFormTemplate I have controls which I bind to fields A and B. Something like:
<asp:TextBox Text='<%# Bind("A")%>' />
<asp:TextBox Text='<%# Bind("B")%>' />
For update I have a stored procedure which expects 3 parameters A, B and C. In RowUpdating of ASPxGridView event I check for e.NewValues collection. The problem is that it only contains fields A and B and not C. This is expected and normal because field C was not bound to any control. E.g. NewValues["C"] returns null. But I need the old value of C so I can pass it to stored procedure which expects all three. I cannot just make up a some value because this would overwrite existing value in database.
My hacky solution was to make a dummy control inside EditFormTemplate, bind it to field C and make it invisible like so:
<div style="display: none">
<asp:TextBox Text= '<%# Bind("C")%>' />
</div>
Now, the field C is bound and in RowUpdating event I can access it with e.OldValue["C"].
But this is a hacky solution and I dont like it. Is there a way to "bind" field C in code-behind or in some way to force field C to appear in OldVaues and NewValues collections?
For getting values which are not bound to a UI element use the ASPxGridView.GetRowValues method. Pass the FocusedRowIndex and the column name of the column, then cast it to your desired type.
string C = ASPxGridView.GetRowValues(ASPxGridView.FocusedRowIndex, "C") as string;

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)

Text='<%# Eval("LocationType")%> vs Text='<%#Bind("LocationType") %>'>

What is the difference in:
Text='<%# Eval("LocationType")%> vs Text='<%#Bind("LocationType") %>'>
Thanks
The Bind keyword works like Eval to display data and can retrieve the value you've entered when updating or inserting a record.
In addition, Bind is very useful in TemplateFields used in the GridView and DetailsView. Bind stores the value of the bound control property into a collection of values that the FormView control automatically retrieves and uses to compose the parameter list of the insert or edit command. The argument passed to Bind must match the name of a field in the data container.
For example, the textbox in the code snippet provides the value for the notes field.
' />
The .NET Framwork 2.0 introduces Eval(). Eval() is a shortcut for Container.DataItem().
Since Eval() uses Reflection, it causes overhead. From a optimization standpoint, it is better to use Container.DataItem().

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 dropdownlist selected value if the value does not exist

I have a control that holds a dropdownlist that holds variables (A, B, C, N/A). The variables are pulled from a class. When an item is submitted, in the database it will store the letter and an identifier. If the database entry with the identifier exists, this code runs fine, if the database does not hold an identifier for the entry (it does not exist yet) then I get an error.
Code:
<EditItemTemplate>
<asp:DropDownList runat="server"
ID="ddlQualityTypes"
DataSource='<%# CodeLists.QualityTypes() %>'
DataTextField="strCode"
DataValueField="strCode"
SelectedValue='<%#Eval("strQualityCode")
== null ? "A" : Eval("strQualityCode") %>'
/>
</EditItemTemplate>
Any ideas on how to get around this?
EDIT: strQualityCode is the name of the variable that is databound to the object holding which letter corresponds to the item.
I would make the field nullable in the database, and make it an optional parameter in your stored procedure. If the value of the dropdown is null or empty, don't pass the parameter to the stored procedure.

Resources