Refresh a form from class after insert() - axapta

I want refresh a form from a class. I want the refreh after a insert() statemant. Is here a better solution for this problem.
Here is my code:
try {
do {
row++;
this.readRow(row, cells);
ttsbegin;
this.insert();
ttscommit;
type = cells.item(row+1, 1).value().variantType();
}
while (type != COMVariantType::VT_EMPTY);
<--------
After the while the insert is finished and at this position where I will the refresh.

Usually you would pass a reference of the form's data source you want to refresh to your class and then call research on it to refresh it so that your newly inserted records appear.
Alternatively, although IMHO not that clean, is to pass a buffer of that form's data source to your class and then (maybe after checking via isFormDataSource) access and refresh the data source via the buffer's dataSource method.
A third way would be to implement a dedicated method on your form solely for the purpose of refreshing the data source as described above. When creating the instance of your class you then pass a reference to your form so that you can call that method when needed.
Update: To see how to call a method defined on a form from a class see the class Tutorial_Apply and form Tutorial_Form_Apply which shows how to call the method applyText which is implemented on the form. Likewise, you could define a method refreshData which calls research on your data source.

Related

What is the "best" way to handle alternately Post and Get Actions?

I am trying to build sth pretty simple, but I try to do it the correct way. But I struggle to figure out what is best.
I have a process chain where the user has to fill in some fields in different forms. Sometimes it depends from the user inputs which form the user is shown next.
[HttpGet]
public IActionResult Form1(Form1Vm f1vm)
{
return View(f1vm);
}
[HttpPost]
[ActionName("Form1")]
public IActionResult Form1Post(Form1Vm f1vm)
{
//process the data etc
//prepare the new viewmodel for the next form view (f2vm)
//Option1:
return View("Form2", f2vm);
//Option2:
return RedirectToAction("Form2", f2vm);
//for Option 2 I would need an additional HttpGet Action Method in which I
//would have to call Modelstate.Clear(); in order to not have the
//immediate validation errors on page load
//also all the properties of my viewmodel are passed as get parameters
//what looks pretty nasty for me
}
//More form views action methods should be added here...:
What is the better way? As mentioned in my comments above I have quite a big disadvantage for using the RedirectToAction option. However if I use the direct View(); call, I don't take care on https://en.wikipedia.org/wiki/Post/Redirect/Get and the user cannot simply refresh a page without getting a warning that his form is submitted once again.
Do I miss another way or don't see something obvious?
Edit: I just thought about a 3rd way, which I have seen quite often: Not transfering the whole VM to a HttpGet method but only the ID. I'd then have to load all the data stored previously directly from the db, map it again to my new VM and then call the View(); with this VM. Right now I think this is the "best" solution, however I feel like it is pretty laborious...
As per the dicussions, I would suggest using depending on your preference :
1) Save to db at the end of each form post and as you suggested use the I'd to redirect to a GET.
2) Depending on the the number of form pages and your requirements, retrieving values that a form needs on the get would be standard practice. This ensures that if a user drops off a form at any stage you can then start them off where they left off.
3) I wouldn't setup the viewmodel for the next form in the post of the previous. Generally as part of the single responsibility principle you want to ensure that your methods have only one reason to change.
4) PostRedirectGet pattern should be implemented with this to ensure data is not saved multiple times if a user refreshes after a post.

ErrorBinding Spring portlet MVC

Disclaimer: I wished I had a through understanding before starting working with the framework.
But as it is of now, I'm lacking on that front, and hence the question.
I am working with Spring-Portlet MVC.
I have a flow, where in I take an input on a screen, validate the input, depending upon its result it either render same screen or next screen.
Implementation detail:
I have an action method which takes form backed command object. It checks whether entered input is valid or not. If it is not valid, it populate error message in BindingResult instance it takes as another argument.
We have different render method, to render different screen.
I'm taking command object as an argument in these render method. This command object I'm receiving is same as one passed to action.
Problem:
While rerendering a screen spring-mvc should bind the error message populated in action method. Currently when I take command object as argument in render method spring-mvc is somehow unable to bind that error message. But interesting enough it is able to bind the error message if I don't take command object as argument in render method and rather create a new command object altogether there.
can,some one having better understanding of spring-portlet mvc please explain this behaviour, or tell where I am lacking in understanding.
Regards,
Mawia
EDIT: Just to enrich the below answer: Though I didn't exactly isolated the issue which was causing the said behaviour, but the way I met my requirement was using modelattribute. ModelAttribute can be used either on method or a parameter to a method. It ensures that model will made available to all the call till the view is render(that is my understanding!). So we don't need to take command object as parameter in Render method, just annotate the commandObject parameter in action method with ModelAttribute and then you can get the same object returned from model as suggested in the answer below.
I don't think the command/model object should be an argument/parameter in the render method. I have had the same issue trying to get the validation error messages when command/model is defined as argument in render method signature. I typically have the command/object creation/populate in a separate method, like this:
#ModelAttribute(value="address")
public Address getAddress(#RequestParam Integer id){
Address address = null;
if(id != null){
address = myService.getAddress(id);
}else{
address = new Address();
}
return address;
}
If I still need to access the ModelAttribute/command object from the render method, I typically get it by:
#RenderMapping
public String showAddressPage(ModelMap modelMap){
Address address = modelMap.get("address");
//make any additional changes to address
}
I used this example as reference article

Override methods in dynamic form

Is there any way to override method in dynamic form?
I've created a form from code (create Form, adding DataSource, etc. and then FormRun). The problem is with the datasource validation. In normal form (in the AOT) I'd use return true in validateWrite to prevent normal validation on table.
How I can achieve this only from code? (or more precisely: when I've only class to play with)
I think the FormBuild.addMethod is what you are looking for. Provide the FormBuildDatasource object as the third argument to the addMethod method.

Where was super() called from?

On a form data source (SalesLine) I have a validateWrite method, which in turn calls the super() method to call the validateWrite method on the SalesLine table, amongst other checks.
In the SaleLine table I have custom functionality for recording, and sometime stopping, data changes.
I don't want this functionality to be triggered when I write to SalesLine from my new form. Therefore I want to check a condition, within the validateWrite method on the SalesLine table, to find out if the validateWrite was called form my new form. This will allow me to skip the data change recording/stopping if the SalesLine write was called from my new form.
What is the correct approach?
I could create a boolean recordSaveChecks and set it before calling SalesLine.write(), but is there a better way?
Edit: To clarify, I do not have form specific custom verification to add, I have a system-wide verification (therefore sits on the SaleLine Table), which needs to be skipped when called from from 1 specific form.
The best option may be to move the customization that is form specific onto the form's data source rather than on the table itself. But if you true want to add form-specific code to the table, you can see an example in Tables\Address.update(), where it checks this.dataSource().formRun().name() to determine if it has been called from the relevant form.
You could put your code on the SalesLine DataSource in the ValidateWrite() method, before the super call Something like this:
ret = YourCheckGoesHere;
if(ret)
{
ret = super();
}
else
{
info("Why validation failed goes here");
}
return ret;
Then you've implemented the validation logic into Table not into the Form because you need the validation to be system wide but you need to prevent this validation when Insert/Update the record.
I think you can by override write() method of Form DataSource and use SalesLine.doInsert(); and SalesLine.doUpdate();

Cache Expiration event asp.net enterprise library

I wanted to know if there is any event which occurs each time a cache item is about too get expired or any event which is raised when a cache item is getting expired.I am using enterprise library in asp.net for caching.I want to store some data in my database when a cache is about to get expired instead of calling a function or invoking an event myself I was thinking of using the already managed cache library event which is being used to flush or dispose cache items.
Assuming you're using the Caching Application Block then you specify a callback delegate when you add items to the cache.
Receiving notification of an item's removal from the cache requires that you specify the class implementing ICacheItemRefreshAction on the call to the Add method
You need to supply a class implementing ICacheItemRefreshAction:
[Serializable]
public class ProductCacheRefreshAction : ICacheItemRefreshAction
{
public void Refresh(string key, object expiredValue, CacheItemRemovedReason removalReason)
{
// Item has been removed from cache. Perform desired actions here, based on
// the removal reason (for example, refresh the cache with the item).
}
}
As you can see, when an item is removed, this Refresh() method is called with the key and the object that's being removed. You just need to cast the expiredObject parameter to the correct type and arrange to have it stored to the database.
As documented here: http://msdn.microsoft.com/en-us/library/ff664621(v=PandP.50).aspx

Resources