C# ; Move from one (HTML) table to another - c#

First of all, this is not SQL related.
I have two tables where data shows. (As shown below, pretend the table on the right has no data in it.)
You have to imagine it's a list of items that you can order on the left side, and once you click on an item, it adds it to the table on the right.
This has been the case on our ASPX website, but we're now making/converting that in C#/MVC (See picture below of ASPX version)
I am not asking for code, but reccomendations/advise on how I should do this.
Possibly JQuery, or maybe in the Controller.
In the Aspx.cs
void ArticlesGridViewItemsDisplay_ItemClicked(object sender, Dictionary<string, object> data)
{
using (var dbConnection = DbConnectionFactory.CreateConnection())
{
int materiaalId = Convert.ToInt32(data["MateriaalID"]);
var materiaal = Materiaal.FetchById(dbConnection, materiaalId);
_orderFormData.AddOrderItem(new OrderLineDto(materiaal, 1));
OrderFormRepeater.DataBind();
}
}

You could go the route of using a framework such as Angular and Knockout but both of these is likely to require you to implement a MVC type model on the client in js/json. I've used both KO and ANg with MVC applications and although they are both excellent I've sometimes found them a bit of pig to work with. In your case you appear to have a very simple requrement - its just seems to be basic DOM manipulation and a dynamic selection. Ang/KO frameworks are of course excellent at doing this sort of thing but I wonder it its a bit of an overkill for you? What you've described would be very easy to acheive with a light touch of jQuery. And lets face it jQuery and .Net do have a longer heritage than the new kids on the block.
I know I'm being somewhat vague and thats simply because there is no absolute right answer to this question. It all depends on how you intend to extend the application and on whichever method your most comfortable with. One thing however is clear in my mind: Using a MVC controller for all the work would result in needless requests to server which will be slower UX and increase the burden on the server. Neither of which is desirable. Better by far to keep as much as possible in the browser. And on the server, use WebAPI to respond to you ajax requests, MVC for your POSTs and html GETS.
I wonder how many cages I rattled with these comments... bring on the debate!

Related

MVC / ViewModel - Trouble with Best Practices in ASP.Net Core 3.1+

I'm relatively new to web development in my current role and we have an MVC SPA type application I'm developing with my team. I can't really share any code directly as it's all the property of my company, so generally:
We're currently working to make a wizard that will collect several points of data and combine it all into the backend's SQL Stored Procs for inserting into tables. To start we've built a viewmodel that injects in and displays the possible options for various fields / drop downs. As choices are made in the drop downs it draws in new layers of the wizard.
To keep track of everything selected, I feel like our current strategy might be suboptimal - or more complex than needed.
When the View is interacted with, we're serializing the #Model into json, pushing it into the controller along with any data gathered from the user, de-serializing it into the ViewModel type, and sending it back in to the new partial view - storing any modifications from that action.
This keeps track of the changes as the user works through the wizard and allows us to redraw the primary div/page space to get new information as the context of what we're asking for changes.
I've seen websites do this with Forms or other things like modal pop ups, but as this is a multi step conditional wizard I chose against using that pathway as the views quickly became a mess of conditional razor checks and in page updates.
I know enough to know I'm not sure what best practices are in web development and I'm finding it difficult to extrapolate from various tutorials around the web into the complexity of this particular project.
I can give a generified example of code below, but hopefully the explanation above will trigger someone's brain to help short cut me to a cleaner way to do this.
public class XController : Controller
{
...
public XController(XRepository xRepository, IViewModelFactory viewModelFactory, Input input)
{
_xRepository = xRepository;
_viewModelFactory = viewModelFactory;
_input = input;
}
public IActionResult XIndex()
{
return PartialView(); //Draws an add/edit/delete set of buttons to begin the wizard. Assume the Add button is clicked leading to the next method.
}
public IActionResult DisplayAddJob()
{
//get list of task and connection types so user can select
_taskTypes = _xRepository.GetTaskTypes().ToList();
_connectionTypes = _xRepository.GetConnectionTypes().ToList();
_queryTypes = _xRepository.GetQueryTypes().ToList();
//build and return viewmodel so u can bind it to AddjobIndex dropdowns
XViewModel xvm = _viewModelFactory.Build(User.Identity, _taskTypes, _connectionTypes,_queryTypes, "Miscellaneous", _input.Test);=
return PartialView(xvm); //The initial view model creation / draw happens here
}
[ActionName("JobQueryWithPriorData")]
public IActionResult JobQuery(string vConnection, string vmJson)
{
xConnection vc = JsonConvert.DeserializeObject<xConnection>();
xViewModel xvm = JsonConvert.DeserializeObject<xViewModel>(vmJson);
xvm.SelectedConnectionId = (int)vc.ConnectionId; //we equip the view model with data that changed in the page interaction
return PartialView("~/Views/Miscellaneous/X/JobQuery.cshtml", xvm); //redraw the view in the main content pane with the updates.
}
...
}
This pattern exists all across the controller. An example of the .cshtml code #razor / javascript calls into the Controller are as follows:
Razor:
<td class="td-main-table" valign="middle">
<button type="button" class="y" onclick="SelectButtonClicked('#JsonConvert.SerializeObject(Model.ConnectionList.Where(x=>x.ConnectionId == ct.ConnectionId))','#JsonConvert.SerializeObject(Model)')">
</button>
</td>
Javascript:
function SelectButtonClicked(vConnection, viewmodeljson)
{
var functionalUrl = '/X/QueryToTableWithPriorData'
$.ajax({
url: functionalUrl,
type: 'POST',
data: {
vConnection:vConnection,
vmJson:viewmodeljson
},
success:
function (response) {
$('#displayDataPartialView').html(response);
}
});
}
This methodology is working. We're slowly, over the life of the wizard, able to grab the users selections and keep track of them. I'm just curious if there is a better way to do this, as I'm certain if there is I'm not aware of where to hunt for it. I believe in the old days people would just store stuff in ViewData objects, but I didn't really start web dev until .net core 2.1.
My team and I have full creative control over this application, it's internal and something I built from the ground up specifically for our team to put internal tools into, it's fairly lightweight currently and I'm willing to modify it to have a better foundation going forward.
Would it be better to store the user selections in a table tied to the users session and just recall the data at the end of the wizard on submit?
Are forms more flexible than I think they are?
Should I use modal windows instead of redrawing the page every time as a step through this?
Edit:
After a few days of research, while I'm not sure I have the best practices by any stretch, I do believe what we're doing is adequate. I've learned more about client vs server-side rendering and I believe my post came from not quite understanding the two well enough.
I believe the functionality I was expecting was "client-side" functionality from a very server side framework: the ability to step through a wizard's various forms without losing the data as the client goes through. This can be achieved with javascript/angular/react/blazor manipulating the view without going back to the server with a post/get.
In the world where I'm using minimal javascript, the strategy I'm using to turn the model into json in order to attach more data to it on the server side and resend it to the client for further modification SEEMS appropriate.
I still am interested to see if anyone has a best practice, so I'll leave the question open for a bit longer to see if anyone has anything. It's possible I should add a more client side layer to the solution as currently my thought was to try and maximize how much I leveraged the C# portion of web development. It seems like that might be my overall issue here.
Additionally, I spent some time looking into ViewComponents at a the suggestion of a commenter, Xinran. They are neat and do perform similarly to the PartialView methodology I'm using. I like how they work, but they produce the same exact scenario. They are mostly server-side tools, and I still, in the end, run into exactly the scenario that makes me wonder if this is the best way to handle a wizard with multiple steps that evolves off the user's previous choices.

Getting list of properties of a DataType from current page

Good evening!
I am currently working on the backend of my application and I need to get a list of all properties of a certain datatype but only the ones in the current page.
listFiltersCms = _umbraco.ContentAtRoot().SelectMany(c => c.Descendants<DataFilters>()).ToList();
This line above gathers all the filters from all the pages, but I want the filters from a specific page (can be currentPage).
I have tried something like this:
var listFiltersCms = _umbraco.AssignedContentItem.SelectMany(c => c.Descendants<DataFilter>()).ToList();
But without any luck :( Any ideas?
Not entirely sure what you mean by "the backend of my application" - are you inside Umbraco or on a public website?
I ask because there is a fairly straightforward way of getting all info on a specific datatype, but it is not really meant to be used on public facing websites. It can be, but it might be taxing on the system as I believe it queries the database directly, which is not ideal.
Anyway, you might want to take a look at the DataTypeService:
https://our.umbraco.com/Documentation/Reference/Management/Services/DataTypeService/Index-v8
And here you can see what options you have for using it (not very explanatory, but I spot a few methods you could probably look into):
https://our.umbraco.com/apidocs/v8/csharp/api/Umbraco.Core.Services.IDataTypeService.html
If you decide to use the service in a scenario where there will be a lot of requests, maybe consider caching the output to spare the database.
The way I solved this issue was by getting the page in the correct model. In my case all I had to do was:
(_umbraco.AssignedContentItem as PageModel).FilterCustomMeasures;

ASP.Net MVC 2: Using a viewmodel destroys my model binding

I guess this is a story of how frameworks cheerfully do 95% of what you need, but then frown disapprovingly at that final five percent; inform you that if you want to participate in nonstandard malarky it's your own business, thank you very much, and it'll be here if you decide you want to return to doing things it's good at. Generally speaking it's inevitable that this final five percent will contain some version of a must-have feature.
I have a strongly-typed view which updates a data object. I've used idiomatic MVC2 helpers, eg Html.TextBoxFor(model = > model.Name). I've used Editor templates for nested objects. (My backend is a collection of Mongo documents, so I need to represent complex types).
Then I need a dropdown. It turns out dropdowns are a bit finicky; no problem, I'll make a viewmodel instead of passing in the item directly:
class itemViewModel
{
...
public Item item { get; set; }
public IEnumerable<SelectListItem> dropdown { get; set; }
}
public ActionResult()
{
return View("Update", new itemViewModel(item, dropdown))
}
... that works fine, the dropdown populates. But! my view requires updating:
Html.TextBoxFor(model => model.Name) ->
Html.TextBoxFor(model => model.item.Name)
Great, problem solved. Oops, now my model binding doesn't work. I debug and look at the Request.Form values: Oh. item.Name instead of Name. Makes sense. I tell my Update view to expect an itemViewModel instead, and the binding works.
Oh wait, no it doesn't. Because I have nested objects that use editors. They are strongly typed and they don't know that the model they're receiving is actually a property of the viewmodel. So they're still spitting out Address.City instead of item.Address.City, and the binding fails.
I can think of several workarounds:
Write specialized custom model binder
Put the whole damn form into its own typed editor, so it gets the item model without knowing it's a property
Kill the viewmodel and hack the dropdown using the ViewData dictionary
Quit using the HtmlHelpers and hand-write the whole form
Write my own HtmlHelper extensions that will take a lamba and a model object as parameters.
Put every label/field grouping into an individual editor template.
All of these feel like either overkill or sloppiness. Viewmodels seem to be a clean, helpful approach. Does using them mean that I have to be sloppy in other areas, or reproduce minor variations on sizeable chunks of the framework? I taught myself C# over the last three months (a graphic designer trying to figure out what the hell static typing is with no CS background was probably pretty funny to watch). I work in isolation; there's no one to learn best practices from. I feel like if I don't learn some of them, I'll end up with an unmaintainable dung heap. So, your opinions are appreciated.
Sigh. A couple more hours of Googling and a few shots in the dark, and it appears that there is an unbelievably straightforward way for doing this, using the Bind attribute:
[HttpPost]
public ActionResult([Bind(Prefix="item")] item)
{
//item's complex types populate correctly
}
The attribute seems to be smart enough to reach into the complex types.
I will leave this as a tribute to my own ignorance, and in hopes that some other hapless n00b will find an answer quicker than I did.
Daniel, first off I should say that I commend you on your efforts and taking on .NET , C# and ASP.NET MVC all in one big bite. Ok, so you're frustrated and I relate to that. It's happens to all of us every now and then.
I should let you know that I'm not a fan (not in the least bit, in fact) of ASP.NET MVC (Problems with ASP.NET MVC Framework Design) and so I can't give you a worked out solution to your problem. But here is how I'd like you to see the situation you're in:
You're in a maze and you've made one wrong turn somewhere and you're going deeper into the maze but you're not going to find a way out. So what you need to do is back out till that wrong turn and see if there is another route. So starting from where you are, ask yourself, "why" for every step/change you've made and back up one step at a time asking why. does that make sense? you'll eventually get to a point where you have other alternative ways to tackle the same (original) problem.

C# - Naming a value combined "getter/setter" method (WebForms & Binding)

Looking for some help on some names for a project I'm currently working on. I don't have a compsci degree so I don't know what to call this.
I have a method called TryToGetSetValue(Direction direction, object value, object valueOnFail)
Then there would be a Direction enum
public enum Direction
{
ModelToForm,
FormToModel
}
Background
This is a legacy ASP.NET application. The models, database, and mainframe are designed poorly. I can't put in MVP or MVC patterns yet (too much work). ASP.NET code is a ridiculous mess (partial pages, single-page design, 5x the normal amount of jQuery, everything is a jQuery UI dialog). I'm just trying to put in a bridge so then I can do more refactoring over the next year.
I have ~200 fields that need to be set on a GET and written back on a POST.
I trying not to x2 these 200 fields and have 400 lines of code to support.
What would you call my method? enum? Is there so other form of binding that would be easy to use instead? I'm not a fan of the DetailsView or FormView built-ins of ASP.NET WebForms.
You probably want a Property
Just my $0.10 here, but how about:
public void AccessProperty(PropertyAccessType accessType, object value, object valueOnFail){...}
public enum PropertyAccessType
{
ModelToForm,
FormToModel
}

ASP.NET MVC C#: Bringing in data from multiple tables/queries into a view

Ok, I'm still getting the hang of asp.net and the MVC framework and converting my knowledge over from classic ASP and VB - so please be gentle.
I've got my first view (/home/details/X) functioning well thanks to previous help pointing me in the right direction, now I need to add data from multiple tables and queries/views to the MVC view (I hate that SQL and MVC both use the word view for different meanings).
I'm not looking for someone to write the answer for me (unless they're feeling really energetic), more so for someone to point me in the right direction of what I should be looking at and reading up on to understand it and do this myself.
My problem
There are multiple datasets which I need to display in this view, and each different data set has a proper PK/FK 1-M relationship established, and the resultant records would need to be looped through.
How I would have done this previously
In my classic ASP days, I would have just defined the SQL query at the head of the page where the data was to be used, with a select statement along the lines of:
SELECT * FROM query_name
WHERE query_uniquecolumnname = Request.QueryString("value")
Once that was done, you'd set the do while query_name NOT BOF/EOF up, then drop in the field names you wanted from that query and it was all done.
How do I acheive this now?
So, fast forwarding from my classic ASP knowledge, how do I acheive the same outcome with MVC?
The tables/views I wish to use are already defined within my data model (and the relationships are showing up in there which I would assume is a plus), I just need to work out how I could call these within the page and use the ID of the record being displayed in the Details view to ensure only related data is displayed.
Thanks in advance
The concept you are looking for is called a ViewModel. Essentially this is a custom class that you write that contains all the data that would be used in your view. So it is responsible for amalgamating all the data from the different tables and exposing it as properties. If you're using a data access layer, this is often as simple as bringing a few entities together. If you're using raw SQL to do it, then you would execute your queries when the properties were accessed.
Then you would make your View inherit from the ViewModel, like so:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.MyViewModel>" %>
Now in your View, you can access all the different properties of your object simply by writing statements like:
<%= Html.TextBox("MyProperty", Model.MyProperty) %>
To construct your view from your controller, create a new instance of your class (MyViewModel), pass it the ID of the details record that you need, and the logic in your class will take care of getting the right data. Then return your view from your controller like normal.
var myDetailsModel = new MyViewModel(detailsID);
return View(myDetailsModel);
I would recommend reading this primer on ASP.NET MVC
http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx
It covers most basic scenarios you'll need to get up and running.
If however you want to combine multiple resultsets into one, and then return it as a view, you should create a custom object, and map the resultset to it, then you can bind against your custom object in the view.
When I need to display multiple things like this on a web page, I use typically use RenderAction to do it.
RenderAction allows you to use a controller method dedicated to that particular part of the view (a subview, in effect), so you can pass a single data set of strongly-typed data to that "subview".
RenderAction is in the Microsoft.Web.Mvc ("futures") assembly.
If you are new at all of this, I apologize; this is a bit bleeding edge, but you're going to need to know it anyway. Be sure to check out the NerdDinner tutorial first.
http://www.andreas-schlapsi.com/2008/11/01/renderaction-and-subcontrollers-in-aspnet-mvc/
http://davidhayden.com/blog/dave/archive/2009/04/04/...

Categories