Razor MVC - Object Edit Field Change Log - asp.net

Users modify a DB object in an edit form that I have, pretty straight forward.
I need to implement a 'change log' on this object. I need to record which fields where changed and what they were before and after. I'm using Razor MVC.

I've done this by writing triggers for the table on update/delete. On update/delete of a record, the trigger pushes the record to a History table, in a History database. This creates the change log. Then you would just need to display it; to identify the change would require evaluating each and every field.
There's nothing already built that wold do this for you that I know of.

Related

When passing an ObservableCollection using MVVM Light's messaging, is a copy passed or is a reference passed?

We're working on a new WPF app, using MVVM Light. We've got a customized ObservableCollection which starts as being bound to a datagrid. According to the project's specification we have to start on a form showing the datagrid and then when a user selects a row we show the user a detail view in another form. At this point we're getting the selected row and assigning that to an object which we assign to a MVVM Light message so that the detail view will be able to display the record's details.
Now that we're getting into this we've encountered a complication. The specs require that the detail view be able to navigate through the collection, even though at this point it doesn't have the collection. We had through we could accomplish this through an interface we defined that we called IRecordService, implementing it for each type of record we work with. However the problem is that the record has no idea if its the first record in the collection, the last one, etc. And that's necessary because of buttons on the detail form where people can navigate through the collection. We've been trying to do this with, for example CustomerRecordService, but so far that hasn't worked out. Perhaps it will if we keep at it.
But I've been wondering, what if instead of creating an object that has the selected record in it which gets passed into a message, we instead pass the whole collection and the key to the selected record into the message which then is caught by the detail viewmodel? My co-workers primary concern is how is the ObservableCollection passed, under these circumstances? Is a copy of the ObservableCollection passed or a reference to theObservableCollection that's in the listing viewmodel? I would think its a reference, but wanted to ask to make sure I'm right, or not.
It has to be just a reference. Otherwise messenger would have to know how to clone every single object. But you can easilly check it. After you get an object in your details viewmodel, change it. Add something, remove something and change some parameter of some objects in the collection. Then check if it has been changed in the main form with the grid.

Populating insert values in asp.net dynamic data site?

I'm using Visual Studio 2010 to create a dynamic data site with scaffolding according to: http://www.asp.net/web-forms/videos/aspnet-dynamic-data/your-first-scaffold-and-what-is-dynamic-data
The site displays a SQL table with an "Insert New Item" link, which takes you here:
I have another SQL table which holds some of the information already. I would like to add a function that is called when the user navigates away from the "account" field; the function will query the other SQL table and populate the fields that it already holds for that account.
I'm stuck on where to put the function and how to setup the account field to call it.
It's a couple of years since I did one of these so pardon the details being a bit short.
You can 'override' the default New Item form. In that you can pre-populate the fields with anything you want. I think you have to take care of the Save also, and of setting out the controls on the form and populating them (you've overridden the generated form after all).
Another possibility is to create a partial class which extends the Model class and populates it in a constructor extension (I remember doing various stuff with this technique). There might also be some extension points on the model Context (or whatever its called) which you can tap into - it's pretty flexible as I remember.

How to add/save temporary table on form

We created special form to creating purchase prices for vendors.
New form has almost the same fields as original (so we used PriceDiscTable), but the record/datasoruce was set as temporary table. After user filled mandatory fields will click button, (extra logic behind) and record will inster to database (real priceDiscTable).
The idea was to grand access to trade prices for users that not necessarily has access to purchase prices. In theory everything was ok, but when user with no access to PriceDiscTable open new form, error was shown "Not enougt right to use table 'Price agreements'".
We try set the AllowCheck to false in formDatasource but this only allow us to open the form, but user still cannot add or modify records.
Is there any way to force system to allow user to write data in the temporary table?
Disabling security key or grand access to real table is not an option.
Duplicate table and create with same fields is nuisance (if we use same table we can use data() method to assign fields)
I think that creating a new temporary table with [almost] the same fields would be the best solution.
If the only reason you oppose to this approach is that you wouldn't be able to use data() to copy data from one table to another you can use buf2BufByName() as described here: http://mybhat.blogspot.co.uk/2012/07/dynamics-ax-buf2buf-and-buf2bufbyname.html
You can use RunAs to impersonate another user...perhaps a system user. I don't entirely follow what you are trying to do, but it sounds like this solution would work for you if you know exactly what your custom code is doing and is capable of.
See Classes\AifOutboundProcessingService\runAsWrapper to see an example.
You will not be able to display the PriceDiscTable without giving the user at least "view" access or editing Classes\FormRun to somehow bypass the security key, which is kernel level so it's also not possible.
I agree with 10p where you should create a temp table and then create a custom method handler combined with buf2bufbyname() or buf2buf().
Another option you can screw around with, if you REALLY want to use .data() is using a Common as the datasource. You could add the fields you want on the grid with the common, then you can pass a common back/forth. This has a good amount of form setup to get this working, but it could produce what you want eventually I think.
static void Job8(Args _args)
{
Common common;
salesTable salesTable;
;
common = new DictTable(366).makeRecord();
select firstonly common where common.RecId == 5637145357;
salesTable.data(common);
info(strfmt("%1 - %2", salesTable.SalesId, salesTable.SalesName));
}

Dynamically make tables/columns readonly/hidden in ASP.NET DD

I'm making a security permission system for a Dynamic Data site based on the article Securing Dynamic Data Preview 4 Refresh. The system contains an additional permission kind: "deny an operation for a record/field if a record is not owned by an user".
If an user can read only own objects, we need to have an always enabled filter in List and check permissions in Details. If an user can write only own objects, we need to check permissions in Edit and Delete, remove "Edit/Delete" links from some rows in List, make "User" field readonly and provide its value in Insert. I didn't think about column-level permissions of this kind yet.
So, the main problem, as I see at this moment: too many places to place the same checks (I didn't even think of malicious user crafting POST data). Also I couldn't make make a field in Insert at the same readonly and having a value which is displayed and saved to DB (I don't want to place that in the model partial classes because I think that there are already too many places that need to be edited to implement this functionality).
Is there a single place to deny a read or write operation with an object depending on the object value?
How can I provide a default value to the field, so that it will be shown on the Insert page, inserted to the DB and couldn't be changed by the user before inserting?
The following assumes you're using LINQ to SQL.
Is there a single place to deny a read
or write operation with an object
depending on the object value?
Reads
I know of no simpler way to restrict reads than to add a filter to all the relevant LinqDataSource controls. If you are able to implement your filter generally, you can write one QueryCreated handler, then add a single line registering your custom handler to all the page templates.
Writes
In the Dynamic Data metadata, add an OnValidate partial method to all the relevant tables. If the current user is not allowed to ChangeAction the given record, throw an exception. You will still have to update all the page templates to hide UI elements that the user does not have access to, but at least you can rest assured that the worst that could happen in some unexpected case is that the user sees an error page.
How can I provide a default value to
the field, so that it will be shown on
the Insert page, inserted to the DB
and couldn't be changed by the user
before inserting?
Perhaps look at some combination of adding an OnCreated and OnValidate partial methods. See also: this answer.

Linq update problem

I have an application with user and admin sections. If an admin updates data with the help of sql datasource then it's updated the database. However, when we retrieve data with linq query then it's showing its old value rather than the updated value.
After some time, the linq query automatically shows the correct value.
I think its caching the value, but I find myself helpless. Please help me with this.
When you say
when we retrieve data with linq query
Do you mean you call your select methods again or are you using the current in memory objects?
In either case, you can always refresh an entity with :
Context.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, entity)
Make sure that you're using your DataContext efficiently (ideally one per unit of work).
After each update, make sure you call DataContext.SubmitChanges(); to commit your changes back to the database.
Also be aware that any context you instanciate between your changes being added to another context and calling SubmitChanges() will not reflect those changes.

Resources