I have to implement pagination, number of Items per page and sorting for my MVC3 application.
In my view page I have a List of Items that is coming from the Model. I will be displaying a number of Items (defined by the user) each inside div, per each page. I'm not building a table.
I know that mvccontrib can build a table with paging, and not sure if that pagination can be styled at all, cause I have to style mine. What is a good approach to solve this?
Check out PagedList (available as a nuget package). I found it really mvc-friendly so far.
For server side paging, I use https://github.com/dvsspr/Halaman.
It is not documented yet, but it is very flexible and it uses fluent configuration.
One very simple use case for you.
#Controller
public ActionResult Index(AdminPageInfo page, SortInfo sort)
{
PagedData<Account> model = accountRepository.Get().AsPagedData(page, sort);
return (model.IsValid) ? View(model) : View("_Error");
}
#View
#model PagedData<Account>
#{
ViewBag.Title = "Account Index";
}
<p>
Total records: <strong>#Model.TotalRows</strong>
<br />
Total pages: <strong>#Model.TotalPages</strong>
<br />
Total records in current page: <strong>#Model.TotalRowsInPage</strong>
</p>
#Html.Pager(Model)
#Html.Sizer(Model) #* Page size changer helper =) *#
#*
Put a dot after the closing brace and you will see the available options.
*#
<h3>Sorter</h3>
<li>
<ul>#(Html.SortLink<Account>(zz => zz.Id, Model, "User Id"))</ul>
<ul>#(Html.SortLink<Account>(zz => zz.UserName, Model, "User Name"))</ul>
<ul>#(Html.SortLink<Account>(zz => zz.FullName, Model, "Full Name"))</ul>
</li>
#foreach (var acc in Model) {
<p>
User name: #acc.UserName
<br />
Full name: #acc.FullName
</p>
}
That's it.
IMHO, the codebase can be hacked easily - just in case you want to implement hybrid paging.
With plain HTML, you can use the Webgrid help in WebMatrix. It has paging support out of the box with MVC.
http://msdn.microsoft.com/en-gb/magazine/hh288075.aspx
Otherwise, any of the major Javascript components (jqgrid, extjs, etc.) can do paging, all depending on what your model source is. If you implement an AJAX datasource, then you need to pass the paging properties back and forth, so the paging can be done server-side efficiently (depending on your database backend).
If you're looking for a primarily client-side solution, I have never had any problems with jQuery's Tablesorter with Paginator plugin: http://tablesorter.com/docs/example-pager.html
If you want to do this server side, the general approach is that you are going to cache the entire result-set server side*, then make (ajax or otherwise) calls to the server specifying which records are needed. You'll pass a starting index and a number of records to return via querystring or form field (as well as some identifier for the query to make sure you're getting the right result set).
*As mrjoltcola points out in the comments, to cache or not to cache is a case by case issue, for larger result sets it may make more sense to make more db calls with smaller result sets. An alternate solution to the big-result-set problem is capping their result-set size and displaying a message advising them to make their query more specific if the threshold is exceeded. I would advise going with your best judgement initially and optimizing if needed.
Related
I have a partial view which outputs a list of editors. Each editor in the list has a delete link, which is called using #Ajax.actionlink, like this:
if(Model.Any()){
<ul>
#foreach (var editor in Model)
{
<li>#editor.firstName #editor.lastName, #editor.emailAddress (#Ajax.ActionLink("Delete", "DeleteEditor", "EditorSurface", new { editorId = editor.id }, new AjaxOptions()))</li>
}
</ul>
}
I've included #using System.Web.Optimization; in my view and am calling the jquery unobtrusive ajax script from my view too:
#Scripts.Render("~/scripts/jquery.unobtrusive-ajax.min.js")
The issue is that when I view source, the rendered mark-up for my editor list items is like this:
<li>John Smith, johnsmith#example.com (Delete)</li>
I was a little disappointed to see the inline JavaScript in the delete links and was hoping for something a little 'cleaner' (possibly data attributes or something?). It strikes me this is going to be difficult to hook into (to provide confirmation messages etc).
Question is, is this the expected output of AJAX in ASP.NET MVC? I'm very new to this so not sure if I'm doing something wrong in my implementation.
Many thanks.
Yes, this is the markup the Ajax.* family of helpers produces. My recommendation in general, and especially in light of the fact that you don't want the on* attributes added, is to avoid these helpers like the plague. You'll have much cleaner and maintainable (though slightly more verbose) code handling AJAX yourself, i.e. just add a standard Html.ActionLink and then use jQuery to attach an event handler that calls the AJAX. Plus, when something goes wrong, as it almost inevitably does, you have full knowledge and control over the JavaScript that is running, rather than being at the mercy of some opinionated Microsoft dev.
In my web development company, we have many designers who have the following dev knowledge and experience:
Client-side web languages (HTML, CSS, JavaScript)
Basic database design (how to create tables, relationships, etc), and
Basic SQL
The problem is that those guys don't know a server side language, such as C#. We want to give them an option to create web apps with their current knowledge.
Basically, they should be able to create data grids, add/edit forms, etc, without the use of a full server side language such as C# or PHP.
We don't want to create new huge new technologies here. We want a simple solution, that is easy to understand and maintain and possibly somewhat open source.
We thought about adding an extension to ASP.NET Razor, that looks something like this:
#DB(table="pages", where="id > 15")
<ul>
#while (row.Next()) {
<li>#row.Name</li>
}
</ul>
Is this a good solution, in terms of performance, design patterns, code style and security (SQL Injections)?
Is there anything open source for this?
Do you have any other ideas?
Here are some examples for a simple app that uses this style:
/apps/pages/index.html
#(DB.Select(table: "pages",
where: "id = ? and date > ?",
params: new[] { Request.QueryString["ID"], Request.QueryString["Date"] }))
<html>
<body>
<ul>
#foreach (var row in Model) {
<li>#row.Name</li>
}
</ul>
</body>
</html>
/apps/pages/create.html
#(DB.InsertOnPost(table: "pages",
fields: "name, description, date",
values: "?, ?, Now",
params: new[] { Request.Form["Name"], Request.Form["Description"] }))
#RedirectOnPost("/pages")
<form action="/pages/create" method=”post”>
<div>
<label for="name">Name</label>
<input type="text" name="name" />
</div>
<div>
<label for="description">Description</label>
<textarea name="description"></textarea>
</div>
</form>
/apps/pages/edit.html
#(DB.UpdateOnPost(table: "pages",
set: "name = ?, description = ?",
where: "id = ?",
params: new[] { Request.Form["Name"], Request.Form["Description"],
Request.QueryString["ID"] }))
#RedirectOnPost("/pages")
#(DB.Select(table: "pages",
where: "id = ?",
params: new[] { Request.QueryString["ID"] })
<form action="/pages/edit" method="post">
<div>
<label for="name">Name</label>
<input type="text" name="name" value="#Model.Name" />
</div>
<div>
<label for="description">Description</label>
<textarea name="description">#Model.Description</textarea>
</div>
</form>
IMHO
I have to say, UI guys are UI guys for a reason. This is where communication and understanding requirements comes in. Both parties should have a clear grasp on what needs to be done to get the end product complete. It should never be a concern to the guys on the front end how to get the information, just like you should never have to worry about which style sheet is being used when you're writing a service or making a view model.
If it's a matter of too much work load on the back end, it may be time to look at just cleaning things up or making things more concise, but not handing off DB access to someone who doesn't know what they're doing.
If you have this much concern over how they can and will access the data, shouldn't that be a red flag to start? It seems to me you'd rather invest weeks (and it will be weeks since you'll have to sandbox everything) in making it safely accessible instead of just plumbing it through for them.
Do requirements ever get you there 100%? No. You will have some back and forth (either UI needs something, or you do) but that's the name of the game. The good part is most of the time you can work in tandem (they are working on how it will look while you give them the pieces they need to wire it up).
I think you have several options here.
Get them to use node.js so they can use their JavaScript skills.
Get them to use Ruby on Rails, they will probably appreciate using a new technology, and you get a great framework to boot.
But probably more importantly, you should ask them what they think. You might be surprised.
Based on the data above, the fundamental conflicting datum is that you want them to be able to program something using a technology that they do not understand. In my experience, this is not a good idea. If no one on your team understands the ins and outs of server side development, you will end up with a low-quality product.
That said - the situation you are describing is quite common and this is thus a good question. My suggestion is that you should reorganize your team and workflow rather than trying to see how you can solve this by using a "simpler" technology (I put it in quotes because often attempts to make something simpler work for one set of problems, but as the requirements change those simplifications just start getting your way and it's then no longer simpler.)
Some specific options:
Hire one additional person with "backend coding" skillz and have them deal with all of the back end work. (Note that it's not all that important which backend language we're talking about - C#, PHP, Java, Python, etc. - the same principle applies - it's a different/more involved set of technical skills required as compared to doing UI scripting. And on the other hand, this person doesn't require any of the graphic design sense which a UI developer should have.)
Or, designate one of your existing team to bone up on these skills and while it will take them for them to learn - you at least have one specific person who will eventually be the guy who knows all about it.
Whoever this person is, should be in charge of selecting which framework to use. And they should do it with as much of an understanding of the particular problems specific to your project, etc.
Additionally, there are some technical approaches that could provide better separation. One idea is you could write API calls that provide JSON data which the UI people can then access using JQuery or similar tools. This way your backend code is all in one file and just returns data - making it more clear who is doing what. Example:
/api/some-data.php: (the "backend guy" edits this)
// do some work to get some data
$myData = ...;
// dump it out as JSON
print json_encode($myData);
/some-page-that-uses-data.html: (the "UI guy" edits this)
<!-- simple jQuery AJAX call -->
<script>
$(document).ready(function() {
$.ajax({ url:'/api/some-data.php' }).done(data) {
// do something to populate the page with the data...
};
});
</script>
(NOTE: You can use JSONP or CORS to get around cross domain problems if you run into that.)
Overall - instead of trying to have UI guys do work in an area they are not familiar with, separate the work so that people can specialize and each one does a good job on his/her part. You don't need a bunch of people to be server-side ninjas - but you need at least one...
I have a Document Type, that has a tab with some properties.
The properties are Upload types, and Simple Editor types.
(Users are supposed to upload images with some image text).
I have not grouped the "Upload" and "Simple Editor" properties, so how do i do this?
Next question,
I want to loop through each group (there should be 3 currently) and display them on my website.
The markup should look like the following:
<div>
<img src="PATH-TO-UPLOAD-TYPE" />
<div>"TEXT FROM SIMPLE EDTIOR TYPE"</div>
</div>
..
<div>
<img src="PATH-TO-UPLOAD-TYPE" />
<div>"TEXT FROM SIMPLE EDTIOR TYPE"</div>
</div>
...
I would like to use Razor for this. Thanks in advance!
For the first part, using the Razor model, you can't. The content object that you get on the front end only contains the properties, the tabs are not included, as they're only really for organising things in the back office.
You CAN get that information using the Umbraco API, but it's pretty database intensive and could potentially be quite slow if you have a lot of properties/tabs.
You'd be better grouping them yourself in your Razor Macro.
for the second part, you can acces the properties of a page via #Model.property. For example:
<div>
<div>#Model.simpleProperty</div>
</div>
What is a good approach in ASP.NET MVC for implementing a complex form where sections of the form are shown and hidden based on a user's inputs?
My background is in Webforms. I am frequently asked to build forms where a user selects an option from a dropdown list, triggering a handful of new fields to appear. A different selection might cause a different set of fields to appear.
In the past, I would handle this scenario via an UpdatePanel and a wrapper Panel around the fields that I want to show or hide. Validation is automatically disabled when the fields are hidden.
Going forward, I'd like to make use of MVC's attribute-based model validation, but is it possible to make the validation conditional on the values of other properties?
Also, how can I handle the toggling of blocks of form fields? I know how to do it manually in jQuery, but I'm hoping there's an approach that ties in with validation and server-side code.
I am liking MVC much better overall, but I haven't figured out how to handle this type of scenario very well. Likely I just need to shift my thinking to fit better with the MVC approach.
Josh,
The first thing I's suggest is to make sure you use ViewModels for the pages that are mode complicated. A ViewModel is basically a Model you create for a specific View; for example, a ViewModel could be a composition of other classes.
As for dynamically changing the fields on your View, the best way is to use jQuery (or any other javascript library) to do it.
I also migrated from a web form environment and I know is difficult to change gears at the begining, but trust me, doing a simple jQuery even handler is much simpler than having to put in place a control panel and then the event handlers.
Not to mention that is much more efficient; update panels are after all making partial posts to the page, sometimes, with jQuery you don't even need to do that.
After a few projects with MVC, I actually now find it time consuming to go and do the Update Panels on web forms ;)
Hope this helps,
-Covo
I know this might not be the answer you're looking for, but I personally don't think complex forms are very user friendly in the first place and I always try to split them up into simpler forms where possible, or to simplify the form. I've come across many forms in websites where there are a raft of "fields" where there should really be a few questions for the user to answer. Simple stuff which gets to the point of what they want to achieve rather than the field values, along with a lot of application specific knowledge needed to set those fields to the right values.
If you still want to go ahead with a complex form, then as the other answers have already stated there are facilities provided by MVC to do that, but there isn't any set way. So, it's down to you to figure out what will work best for your users.
Traditional asp.net webforms did alot of "magic" for you whereas you have to be aware of the work that goes into creating the "magic" in asp.net MVC. The benefit is that with MVC you have more control over what is happening which can also enhance performance.
In asp.net webforms an UpdatePanel is used for ajax calls. If you need to got to the server asynchronously(without doing a full post back) then use ajax via JQuery. See below for example:
$.ajax({
type: "get",
url: "/YourController/YourAction",
success: function (obj) {
//any logic you want to do upon success
}
});
The above example will do an ajax HTTP GET call to /YourController/YourAction.
In order to handle "toggling of blocks", if you don't need to go to the server for data and you simply want to do it on the client, then use simple jquery. JQuery has a function for toggling items.
http://api.jquery.com/toggle-event/
Because of the way MVC works in contrast to Webforms you're stuck with the responsibility of really thinking about what happens on the client and what happens on the server separately as not a lot of meta-data is being passed back to give us that happy Webforms feeling.
However, there is a notion when using the built-in AJAX libraries when you render a form that you can have it auto do an update once it is posted. In a sense, it's saving you the JavaScript/JQuery because it "auto-wires" it up similar-ish to a Panel. In this way you could potentially look at progressively rendering your complex forms from the server as each section is edited, etc.
See MSDN: http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxoptions.updatetargetid.aspx
The relevant code example to give you an idea (unfortunately, it's not in the more readable Razor syntax):
The relevant line is the Ajax.BeginForm where the form tag is rendered. Once the form is posted, the MS AJAX library will auto update the element specified in "UpdateTargetId" specified in the form's AjaxOptions. In this case, the response will be placed into the SPAN element "textEntered" upon reply from the server. Here, you could progressively render more content to the user to fill out, perhaps another form, etc.
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<p>
Page Rendered: <%= DateTime.Now.ToLongTimeString() %>
</p>
<span id="status">No Status</span>
<br />
<%= Ajax.ActionLink("Update Status", "GetStatus", new AjaxOptions{UpdateTargetId="status" }) %>
<br /><br />
<% using(Ajax.BeginForm("UpdateForm", new AjaxOptions{UpdateTargetId="textEntered"})) { %>
<%= Html.TextBox("textBox1","Enter text")%>
<input type="submit" value="Submit"/><br />
<span id="textEntered">Nothing Entered</span>
<% } %>
I'm working with ASP.NET MVC 2 and building a simple business app. Here are some of the details:
The app deals with work orders and
has a work order index view. The
view has a table listing the work
orders, and several controls (text
boxes, check boxes, and drop down
lists) to select the criteria for
which work orders to display.
I'm using viewmodels. The work order
index view has a viewmodel with
properties for each and every
control.
I've implemented paging similar to
what is being done in the answer to
this question:
How do I do pagination in ASP.NET MVC?
I'm using LINQ's Skip() and Take() as
demonstrated, and ActionLinks for the
navigation.
If I load the page and don't
manipulate any of the controls, I can
click on the page number ActionLinks
and move around just fine between
pages of work orders. However, if I
change something, my changes are lost
when I navigate to another page.
For example, if I'm on page 1 and
click an unchecked check box, and
then click on the link for page 2,
the second page of results will load
but the check box will revert to its
previous state.
I understand why this happens, but I'm wondering what is the best thing to do from a design standpoint.
Potential solutions I can think of:
Set all the control values as route
values in the ActionLinks. This
seems really nasty, and could result
in very long URLs or query strings. Actually, now that I think of it this wouldn't work without a way to capture the control values.
Since ActionLinks don't post
anything, replace them with buttons.
Again, this seems like a bad idea.
Change the ActionLinks to links that
fire off a jQuery script that does a
POST. I think this is the most
promising option so far. Do many
developers do it this way?
This seems like a common enough problem, but none of these options feel quite right. I wonder if I'm missing something.
Can't you just save the changes back to the database when the user toggles the checkboxes (using jQuery):
$("input[type=checkbox]").click(function() {
$.ajax({
type: "POST",
url: "/ControllerName/SaveInfo?id=" + {id},
success: function(){
alert("Data Saved: " + msg);
}
});
});
In the end, I wound up getting rid of the ActionLinks for the paging, and replaced them with regular anchor tags. The current page index is now stored in a hidden form value:
<input id="page" name="page" type="hidden" value="" />
<p>
<% for (var i = 1; i <= (int)Math.Ceiling(Model.RowsMatchingCriteria / (double)Model.PageSize); i++) { %>
<%--
If the page number link being rendered is the current page, don't add the href attribute.
That makes the link non-clickable.
--%>
<a class="pageLink" <%= i != Model.Page ? #"href=""javascript:void(0);""" : string.Empty %>><%: i %></a>
<% } %>
</p>
Then I added the following jQuery script, which sets the hidden page value and submits the form when a link is clicked:
$(document).ready(function () {
$('.pageLink:[href]').click(function () {
$('#page').val($(this).text()); // Set hidden field value to the text of the page link, which is the page number.
$('form:first').submit();
});
});
Problem solved.
Best bet is to effectively simulate viewstate by "logging" the changes to a hidden field when a user paginates. To do so:
1) Figure out what data you need to capture and a data format to do so in {ie -- an array of json objects}
2) Setup the link that handles the prev/next to fire off a method to collect the "changed" things and stuff them into objects and into a hidden field.
3) When posting the form, parse the hidden field, extract data and profit.