I'm currently working on a large project which has a Timesheet class containing a list of TimesheetEntries. There is an edit page for this that looks like:
<!-- Other timesheet properties -->
#Html.EditorFor(model => model.TimesheetEntries)
This works great, I get a row for each timesheet entry. When I save the timesheet (POST to the server) a custom model binder strips out empty rows before passing a Timesheet to the controller, in other words the Timesheet can contain fewer rows than the POST data.
If there is a validation error I redisplay the edit page and this is where the problem arises.
If model.TimesheetEntries contains n records Html.EditorFor() reproduces the first n rows from the POST data (including the empty rows) rather than creating HTML for the data I pass it! This means I lose a number of rows at the bottom of the table which is clearly unwanted.
Can anyone explain why this is happening or even better tell me how to get EditorFor to work as I expect?
Here's a picture to describe the process:
You may want to take a look at the answer provided in this post Asp:net MVC 3: #Html.EditorFor a subcollection of my model in a template? It may help.
Turns out Html.EditorFor looks in ModelState before using the values you pass it... So to get it to pick up the values I passed it I needed to clear the relevant ones out of ModelState first, ugh.
This question/answer covers it in more detail.
Related
I have a simple <table> of rows using DropDownFor and other elements.
On the page these appear as <somelement name='MyModel.MyArray[0]'>, <somelement name='MyModel.MyArray[1]'>, <somelement name='MyModel.MyArray[2]'> etc. on each row.
If I wanted to insert a row into the middle of my list, for example this is a 'todo list' and I want to insert an item at the top, then it will mess with the MVC model binding because I would have to somehow go through and increment the values so the first row would have to be changed to name='MyModel.MyArray[1]' etc.
This seems like a real pain to do. I am wondering if there's a better way to handle inserting a row into a list dynamically so that when posted it maps nicely to the model.
Technically I see no reason why MVC needs to know the index of the item.
Is there a better way to do this, or perhaps using MVC model binding with DropDownFor etc. is not the best method?
I currently have a collection that can have between 2-4 rows and I am trying to attach these rows to an email body.
However, when I am using the 'Email Notifications' Business Object and the 'Notifications-Send Email' action, it only enters the first row and ignores the rest.
I have attached screenshots below of my process
How can I make it so it enters all rows in the email? If there is a code stage way possible I am open to that also
To add this collection to the email you need to first change it to string, that can be added to email. The way you've built it, you're only adding a value from one cell - the one from that column and current row.
There is no official Utility action that can change collection to text. Closest one I can find is action "Get Collection as CSV" from object "Utility - Strings", but the output is not user friendly.
The other way is to loop through collection [Emails Not Sent] and join the data from collection to a text data item. Afterwards you can use that data item in the email that you're sending.
Finally, I'd like to suggest for you, to send emails using HTML mode. There are numerous advantages to that - you can use html formatting, hyperlinks, tables. It is be also pretty straightforward to create an action, that will output a nicely looking html table ready to be added to body of the email you're sending.
I'm using ASP.NET MVC4 C# and I'm facing a problem with displaying an array in my View:
I'd like to display a number of error messages from my controller to the view, but so far, the content of only 1 array is displayed...
Only the data in "ViewData["mededelingen"] is displayed. The data in ViewData["warnings"] is not displayed, despite the same code.
Below is the code of the view:
When I debugged, I have noticed that the ViewData["warnings"] is not empty, as shown in the next screenshot:
However, it does not display the contents on my HTML page.
Below is the output:
As you can see, only the items in red (mededelingen) are displayed, the items in yellow (warnings) are not.
Below is the code of the controller:
Obviously I'm doing something wrong, but I can't figure out what exactly...
Any help?
Thanks in advance!!
DisplayName gets the display attribute of the model property represented by the string that's passed to it. Since your string is just a sentence, that doesn't make sense. Why are you using DisplayName at all?
Just do:
#foreach (var counter2 in (ViewData["warnings"] as List<string>))
{
<td>#counter2</td>
}
So I'm reading data out of a database and want to display it on a webpage like this:
Name Age Fav# ...other info
Bob 11 15
Joe 13 4
I want to make a website that updates the contents of its table based on the database. I know the number of columns that the database has but not necessarily the number of rows.
I was thinking just writing the .aspx file and generating the HTML and values when the database is read, but I was looking at some similar stackoverflow questions and they advise against it? The suggestion was to create a template .aspx file and just populate it, but how would you do that if you don't know the exact number of rows to make?
Also if I programatically write my own Something.aspx files and create a Something.aspx.cs file, will they automatically link together?
I'm new to ASP.net and C#, so I'm not sure if there's an easier way of doing this.
Since you're using ASP.NET I'd suggest using GridView control to display table data. It has a lot more possibilities (like built in paging and sorting). And you do not need to know in advance number of rows - GridView will render whatever is thrown at it, turning on paging if nessesery
My data access layer returns collection with rows for single page and total number of rows.
Unfortunately WebGrid component does not allow to specify total number of rows or total number of pages (these properties are read-only).
Has anyone had to deal with this issue before?
You can use the Bind method on the WebGrid to tell the grid to use server side paging.
grdv.Bind(myData, rowCount=10000, autoSortAndPage=False)
Setting autoSortAndPage to false tells the grid that myData is just a segment of the data. It will show all rows of this data regardless of your page size setting. Pager will be built using the rowCount you pass in and not the number of records in myData.
EDIT: I see what your question is now. Check out this article for not using the WebGrid.
Paging with WebGrid
From this page, it looks like you can specify rows per page.
var grid = new WebGrid(source, rowsPerPage : 25);
And this page (look at line 9 from the first code block).
rowsPerPage is only settable through the constructor. This was done to keep the helper simple and avoid handling complex states. Total rows comes from the data source.