How to avoid code duplication if multiple pages look almost the same? - c#

I have a couple of pages for e.g. Product that look almost the same. I have Product/Add and Product/Modify/{id} pages where one is an empty form to add new Product and the second one comes already filled with data for a current product and can be updated with additional information. Because Razor Pages separates this into Add and Modify PageModels, I have a different cshtml view for each of them.
I tried to use ViewComponents to build reusable parts of these views, but they are only good if all you want to do is display data. Because ViewComponents don't support Binding all I have left is somehow send ajax requests and append the data to submit, which even sounds wrong and probably isn't the right approach.
Is there any other way of creating these pages without duplication?

You can create one page for create and edit by sending a new object of the Product model (with no data in id attribute) and a created object (with data in id attribute) in case of editing. And in the view you can do rendering based on the sent object (whether it is new or not).

Related

Wpf MVVM: What exactly needs to be a view?

I'm new to WPF and MVVM and attempting to write a firmware programmer so I can update stuff via USB and save and upload setting/state data. MVVM seems like it could work for this. I currently have pages and can navigate around the app (although the nav service is in code behind for now) but I'm stuck on how to implement things that aren't in the standard 'customer'/'person' examples.
On a couple of pages, there are subsections that I can see being sub-divided into separate views hosted in the page, and these subsections are used more than once in the app.
For instance, I want to have a TextBlock that displays the connection status and updates based on signposts in the connection process, firmware update, backup, etc. Progress bars with the % are another. Sections that are used to display errors, data or a selection box depending on what happens connecting would be another.
Having a sub-section house 3 completely different outputs all stacked on top of one another and shown based on the situation seems messy. I can see that section being a ViewBox and creating a unique view for each case being a better solution there (and possibly the other examples above).
Or take the 'status display', I can see implementing it as it's own view and the page's view model will use a messenger to pass the current status back to the 'status display' view model. I can also see it all just handled by the page's view model via calls to it's own methods. I can also see potentially using a global model to hold the status strings (maybe an enum?) and the view model can be made to pull the correct string into a 'currentStatus' variable.
What is the proper way to approach this? Keep it all a single page? Subdivide the dynamic/changing parts from the static parts?
OP:
Obviously the pages themselves are views, but would it be best to have the 'Status:'display TextBlock and it's value, and the Error/selector section be views also?
If you are asking whether the status and error displays should be UserControls then yes they can be "a view" irrespective of whether the control is using a view model or not.
Incidentally, it is generally better to use DependencyPropertys instead of view models in a UserControl otherwise you will end up having duplicate properties in both the view (so that MainWindow can databind to it) and in your control's view model (purely for the benefit of the user control).
If your UserControl uses DependencyPropertys then both users of the control and your view can both databind to the same set of properties without duplication. In this way you will realise that UserControls have no need for a separate VM.
OP:
...the page's view model will use a messenger to pass the current status back to the 'status display' view model...
Don't do this, this is what data binding is for.

MVC editing complex object stored in hidden fields

Let's say I have a very huge model that contains lists and even those lists can have objects that contain other lists. I want to create an edit form for that in MVC4 (or 5) without AJAX.
So I figured that the first part of that is to store the entire object on the client side in hidden fields. List binding works like a charm, see http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/. Now the complete roundtrip is working, I can push out the entire object to the client in bound hidden fields, it gets back to me upon submit and the posted hidden fields are put into the complex object, nested lists and everything included.
Lists or other objects should become editable based on some action. One scenario is where a single object or list items are displayed as non-editable, and when the user clicks it, it becomes editable in-place, so for example the cells in a grid become textboxes. Another scenario is where a single object or list items are not shown at all, and when the user clicks a button, a popup window appears with the text input fields.
Is there a library or a proven way to do this?
Is there a library or a proven way to do this?
Exactly what for? Displaying a massive model in view for editing? Making a grid editable? Or popping up the records of a grid for editing?
Basically, I think you are overcomplicating this matter a bit. If you apply some separation of concerns here you will find out how easy everything becomes and in fact it's super easy to implement and most importantly much easier to maintain and scale.
Starting from the model, let's assume you've got this all-mighty massive model named Company with the following properties:
CompanyID (int)
CompanyName (string)
CompanyLegalID (string)
CompanyRegistrationNumber (string)
ContactInfo (ContactInfo class)
HeadQuaterAddress ('Address` class)
Branches (List of Branch classes)
Employees (List of Employee classes)
And the list of properties could go on and on forever.It would be easier, super easier to break down this model into smaller models. Make a CompanyModel model with the following properties...
CompanyID (int)
CompanyName (string)
CompanyLegalID (string)
CompanyRegistrationNumber (string)
Then make a CompanyContactInfo model and so on. Getting the idea? Again, separation of concerns simplifies matters a lot. Then, create action methods and views to read/edit these models.
Now for lists properties of the massive object you'd like to do the same. For example, for the list of Employee objects it'd be easier to create a CompanyEmployeesModel model with the following properties:
CompanyId (int)
Employees (List of EmployeeModel classes)
Then create a controller action method to show the list of employees...
public ActionResult EmployeeList(int companyId)
{
var employees = BusinessLogic.Get_Me_Employees_For(companyId);
CompanyEmployeesModel model = new CompanyEmployeesModel();
model.CompanyId = companyId;
model.Employees = employees;
return View(model);
}
Hope you are getting the idea so far. In the view simply create a css-formatted table to show the employee list, razor makes it super simple...
<table class="grid">
<tr>
<th></th>
<th>
Name
</th>
<th>
Phone
</th>
</tr>
#{
var alt = false;
foreach (var emp in Model.Employees)
{
<tr class="#(alt ? "alt" : string.Empty)">
<td class="cmd">
#ActionLink("edit", "Edit", "Employees", new { empId = emp.Id}, null)
</td>
<td>#emp.Name</td>
<td>#emp.Phone</td>
</tr>
alt = !alt;
}
}
</table>
Notice that the first column of the table has link "edit" that takes the user to the Edit action method of the Employee controller where obviously you will do exactly the same you've been doing with smaller models. All I'm doing is separating the logic, models, view and making them simpler, easier to maintain and easier to understand.
Hope it all makes sense to you
Jeditable http://www.appelsiini.net/projects/jeditable which does the same thing and is easier to implement
The very huge model is a business requirement, it has to be edited as one entity, preferably on one page, it makes perfect sense but I can't talk about it. I originally thought (or hoped) there was an easy to describe solution, but apparently, this isn't a common thing in MVC. It would be very different with AJAX, it has its pros and cons. For sure it's more widely used, hence more documented. Without AJAX, there is only one round-trip, which is a bit bigger, but it's a smoother user experience. Anyway, here's a rough guide how to do it the way I asked.
The client-server roundtrip is handled by MVC with (mostly) hidden fields as I said in the question. Later it can be optimized by encoding some stuff in JSON instead of hidden fields, it doesn't affect the rest of the system.
Normal fields are stored in normal editors, not hidden fields. It makes no difference from the perspective of the client-server roundtrip. So these can be edited in place.
Grid rendering is also easy. Server-side MVC grids are suboptimal in this case, because they would send redundant data to the client side. Luckily there are a lot more client-side grid solutions, they are by nature server platform independent. Just collect the required data from the hidden fields and use a JavaScript grid library to build a grid from it when the page loads. Naturally, as I said, the lists can contain lots of data and other nested lists, but in this simple grid, a few necessary columns must be selected, no problem with that.
Now comes the interesting part, how to edit a grid row with all that complex data. Let's say I have a list of Persons in my model, and they have a list of Addresses. There is a Person grid, and when you click on a row, you want the end user to be able to edit additional data for a Person and also his Addresses.
First of all, the Person editor template has to be sent to the client side in advance. We need to put that editor template inside our view, and hide it. Whenever the user wants to edit a person, we create a JS dialog with the contents of that editor template.
We need to bind the Person editor template to a Person object stored in the hidden fields. Based on which row the user clicked, we get an index, and we bind Model.Persons[index] to that template. Knockout.js is a good candidate for JS binding. It does all the field copying back and forth.
An MVC editor template can also contain validation logic. It's no problem in this case, because we rendered the editor template to the client side as a whole. The validation will happen inside the popup window without any kind of magic. When the user presses the save button, validation will run, and when it succeeds, we use the binding engine to copy the popup contents back into the hidden fields.
It is not the simplest of things, but it is very straightforward. Actually, several different JS libraries are needed, not as I hoped. So if anyone wants to edit a complex model on a single page without AJAX, it is certainly possible. It's still not completely documented because I can't share more details. But it has its advantages: only one round-trip, hence faster user experience, and there's no need to maintain state on the server, all the data is retrieved and saved as one entity in one roundtrip.

c# mvc3 controls within a control

MVC3 has entity framework that makes create, delete, edit methods within a controller.
I am making a control panel that allows to edit multiple tables. How do I incorporate a controller(the entity framework) within another controller(the control panel)?
Any clever work around?
For example http://example.com/Control_panel/Another_Controller
Ok for this, there are two ways lets say you have a default controlpanel action in your ControlPanel controller, you can have a variable that comes in and says what you are trying to control, lets call it controlID, you can then use RedirectToAction to go to that action instead, like this
public ActionResult controlPanel(object controlId){
if(controlId.equals(something)){
RedirectToAction(SomeAction, SomeController);
}
}
The other one is you can use the same idea and call the controller action directly. Like this:
var result= new SomeController().SomeAction();
Although this is breaking MVC design as you should have it be a more universal function rather than a controller, as controllers are designed to control datamovement between Models and Views. If I see some of the code I can give you a more specific response.
If you want to edit data from multiple tables from the same page, you accomplish this by use of view models. The data you present to the user in your view does not need to have a 1:1 relationship with a table or a model for that matter.
A view model will allow you to pick data from various sources, present the same to the user for viewing or editing and if the user saves the same, you can pick the view model from your controller action and use that data to update one or more tables.

When do you use Html.Action over Html.Partial

I still don't get the primary purpose of Html.Action in asp.net mvc. I have been using Html.Partial every time I need to load up a partial view or wanted to split up some code in a view to clean it up.
Where does Html.Action fit into all of this (e.g. where would you want to use Html.Action and not use Html.Partial)?
Edit
The answers seem to be use Html.Action for dynamic data. I don't get this as you can use Partial Views for Dynamic data as well.
For instance if a user on my site edits a row. A ajax call is made to a method and I go grab that row from the db. I then return a parital view of a form that has all the data on it ready for editing. If an error occurs then I return a json result with the error method and my javascript consumes it and alerts the user.
If all is good then the rendered html is put into a jquery dialog and displayed to the user.
Is it because you can use the "ChildActionOnlyAttribute" that makes people use Action instead?
Ankur has the right idea but I find you can really simplify the concept down further.
For me it comes down to What versus How
If you know what you want to render but not how it's likely you'll use a partial to let it determine how to render the information.
For example, maybe your view model is for an invoice. Your invoice view model probably already has all the information you need about the invoice itself, including an enumerable of the line items on the invoice perhaps. A partial might be a good choice for the line items so that it's self contained. You already have the line items details (the what), but a partial will handle how it gets rendered (the how)
On the flip side, maybe your invoice view model has a customer ID on it but no actual customer details. Here you don't have the what, so you'd pass in the customer ID to an Action and it'll get what data it needs and pass it off to the view to render how it seems fit.
So in summary if you already have all the data you want to work with, just stick with a Partial, but if you are missing information that you need to obtain, Action would be better.
Where this get really fuzzy around the edges is when a Partial view includes the ability to retrieve it's own data via Ajax (or other technologies). In which case you might be able to get away with making that Customer details portion in my example, a Partial, and have it retrieve the data it needs Using Ajax after the client get's the response. But that's more up to you if that sort of thing even makes sense for your implementation.
Addendum:
It's worth noting that if you decide to try out ASP.NET MVC Core, ChildActions are no longer available. In which case your choices will be limited to partial views, ajax, or the newly introduced feature of Components. The last of which is similar to ChildActions, but slightly different in how they are implemented.
Perhaps an example will make this clearer.
Let's say you have a menu which appears on every page, so you put it in your layout. The menu will never change - there is just some basic navigation links, Home, About, Contact us etc, so you just use a normal partial view. This will work fine - as the content is static - you don't need to go to a database to get the data. You can just use #Html.Partial("Menu");.
Later you decide you need to change the menu so that it gets all the links from a database. You update your partial view to have a model that is a List<string> - one for each link.
Now, if you still want to just use a Partial View, every action would need to query the database to get the list of links, and every Model for every View would need to have a List<string> property for the links, so that it could pass this to the Menu Partial View. This would be a bad idea.
Instead, you would make a new Child Action GetMenuLinks() - this would query the database to get the links as a List<string>, and pass this to the Partial View. This puts the Child Action in charge of getting it's own data. This means you only need to have this query in one place, the 'About Us' action for example doesn't need to worry about getting the list of links for the menu.
Partial views
Use for sharing subsections of view markup between views. Partial views can
contain inline code, HTML helper methods, and references to other partial
views. Partial views do not invoke an action method, so they cannot be used
to perform business logic.
Child actions
Use for creating reusable UI controls or widgets that need to contain business
logic. When you use a child action, it invokes an action method, renders a
view, and injects the result into the response stream.
I use Html.Action() to load dynaimc content that I do not wish to contain in the view model (for instance, user information in a sidebar). It is very useful for keeping input and output view models identical.
Note that I always use Html.Action() in conjunction with applying the ChildActionOnlyAttribute to the controller method that I am calling so that the HTML fragment is not accessible via the URL.
Use Html.Partial when you require a subset of your view model to render the section in question--usually it is something that has to do with what you're working on. If could be a subsection of a form, a relevant content piece related to the main view etc. A partial receives its model information from the parent view.
Otherwise use Html.Action to render content that is independent of your main view, such as a navigation piece, an aside, or other distractions. Html.Action uses its own model provided by its controller, rather than provided by the parent view.
This question is answered (and elected for 149 times!) here:
Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction
Update
Sorry, meant to send you these postings rather
MVC Html.Partial or Html.Action\
#Html.Partial() Vs #Html.Action() - MVC Razor
Hope this helps.

Filtering Pane, ASP MVC 3

My plan is to create a a two-pane page using ASP MVC 3. The left pane should be a small filter pane and the right the main content, showing a list of objects (say products).
Initially all products will be shown since no filter is applied. When selecting "only red", only red products are shown in the list. When further selecting a price range, only products in that price range will be shown.
Functionally the plan is to implement the filtering pane as a treeview with checkboxes (to be able to drill down to more and more specific filtering options), graphically it will probably be enhanced in some way to improve usability.
What is the best way to implement the coupling between the filter pane and the main list? Everything should work server side, but should of course use javascript (jQuery) when possible for direct feedback.
The simplest way is probably to make it closely coupled solution, calling a specific Asp MVC action using a custom-built javascript (with fallback to a form post). Doable enough, sure, but how to make the solution reusable? Also it would be nice to not loose all filtering data when navigating forward and back, i suppose GET arguments is the only decent way to do that?
Are there any best practices, any guidelines or anything to base this on to make a nice modular structure for filtering.
Victor, I recently had to solved this same problem. I'm not promising it's the best way but it's pretty clear and should even work well in case JavaScript is disabled (who even does that anymore?).
Create a that calls the action with all the field-selectable search options like "only red".
To that same form, add empty, hidden value for the things not directly as fields (paging, sorting...)
Setup your form with the excellent and very easy to use JQuery.Forms (http://www.malsup.com/jquery/form/) to make you form submit via JQuery (all your form values will be passed as JSON on form submit).
Make your back/next/paging/sorting links pass their individual values via query (no-JS fallback) and use JQuery to capture their click events. The JQuery click events on those links should assign the value of the value passed by the link (page number, sort column name...) to the corresponding hidden field in the form and call submit (with thanks to Jquery.Forms will submit via AJAX).
When you configure JQuery.Forms, you can define a callback method. In the callback method take the result (the HTML returned by your action that should contained your filtered+sorted+paged result) and replace the document (or DIV if you used a partial action + view) with that.
The result is a JQuery solution that works when JS is off. You also have very minimal JS code to write other than wiring the event handlers.
I'm not sure if it will be helpful but in MVC 3 you have access to a property called IsAjax from the view so you can do specific things to server a slightly different view when called from AJAX.
Cheers

Categories