I want to update some lookup field of a list when some feature is activated. To deal with this I made a SPFeatureReceiver for the feature. I debug my code and every thing was perfect until I do this:
sourceField.SchemaXml =
sourceField.SchemaXml.Replace("List=\"\"",
string.Format("List=\"{0}\"",
targetGuid));
I dont understand why this happens because I am setting the AllowUnsafeUpdate to true.
The exception that I get is:
[Microsoft.SharePoint.SPException] = {"Save Conflict\n\nYour changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes."}
Please help me asap, thanks
Abel
Related
I have added a 'number_of_members' value to the Customer DocType via customization.
In my application I have tried several ways to update the value. However the value never updates in the webpage. I feel like I'm missing some sort of save or update or commit step.
For example I have tried:
frappe.client.set_value('Customer', '00042', 'number_of_members', 8887)
frappe.set_value('Customer', '00042', 'number_of_members', 8887)
frappe.db.set_value('Customer', '00042', 'number_of_members', 8887)
and also
customer = frappe.get_doc('Customer', '00042')
customer.number_of_members = 8887
customer.save()
In each case I can do something like frappe.get_value, or frappe.get_doc and it shows the value is set to 8887. However it never updates in the web side. This is what makes me think I'm updating some sort of cache or database transaction and I need some way to save it, but have not had any luck.
I am mostly testing this via bench console if that has any bearing on it, but I've tried a couple of the methods in my application code as well.
Relevant documentation:
Frappe Developer API - Document
Frappe Developer API - Database
Turns out the answer is to call frappe.db.commit() after making changes. If someone can point this out in the documentation so I can better understand how I'm missing stuff, I would appreciate it.
I also noticed if you try to Save something in the UI before you send frappe.db.commit() the UI will hang.
Has anyone successfully based an application off the WebIDE Fiori CRUD template? It doesn't seem to be able to handle errors in the batch OData request properly.
For example when you select an item in the master list and click EDIT to update it and I enter a value that I know will cause an error in the backend. The batch OData request is sent and the response is successful (overall) even though internally the update failed. You see a bad request 400 error in the console but the app doesn't react to it.
Using the ErrorHandler.js object you can easily code a message box to show a nice error message, however the app seems to get confused and always navigates to the top item in the list but the ODataModel still has pending changes so if you try to navigate it shows the data loss dialog.
Trying to debug it is very painful given the nature of the code with Promises inside promises inside promises and callbacks firing everywhere!!
Maybe there is a better example CRUD application to base your apps on?
Well.... Some more debugging and I've found that all of the weird issues occurring with the Fiori CRUD template are due to the model defaulting to auto refreshing after changes.
Which typically is a nice feature as the user does not have to hit the refresh button to see changes that have been made after adding a new entry or editing an object.
But this auto refresh on the model seems to play havoc with updates in batch mode.
Firstly, if the batch update is completely successful the app navigates to the first item in the master list - which is should not.
Secondly, when there is an error in the batch of sorts of weird shit happens.
So to fix this I just call oModel.setRefreshAfterChange(false) before the oModel.submitChanges() call (only when updating, not creating). The in the callback after the save is completed we reset auto refresh to true.
The crud app now works as expected and can correctly handle errors in the odata batch update without strange ui updates.
Jason,
but the error message they are providing is very simple, and does not support parsing error body like :
<code>005056A509B11ED199D882461C8C40FE</code><message xml:lang="en">The Data Services Request version '3.0' is not supported for the request payload.</message><
we have to do the code for parsing the errors then show in the message box
in my app i have a relative complex activity/place. Resolving the state (from history token to model) on start of activity causes some server interactions.
On user interactions the activity only updates the necessary parts of the model and therefore safes some server interactions - the activity/model has an inner state.
Is there a way to reflect the state in browser history without (re)starting the activity? (History.newItem(token) also causes start of activity)
UPDATE
Chris' solution "nearly" works but another problem rose: in my ui i have a reset-button (a link to the place with empty token). If i click around the ui the token is updated fine but now the reset button doesn't work. gwt thinks it is in the same place and so it ignores the reset click.
Before this the problem was nearly the same: the token and place didn't change and so the reset button didn't work either.
GWT logs this as "Asked to return to the same place"
So is there a way to let gwt restart the activity regardless of place equivalence?
Go to a new place, but have your ActivityMapper return the same activity instance. That way, the activity is not restarted.
You have to find a mean of updating the activity when the place changes from some other mean though (e.g. browser history). See GWT MVP updating Activity state on Place change for instance.
There is a semi-solution, and although I don't want to recommend it, I'd like to add it here - just to warn against the drawbacks of this solution:
You could add tokens to the History without firing an event by calling History.newItem(token, false).
This is a semi-solution, because:
It works correctly (as long as you build your tokens correctly).
A part of the performance problem is also solved: The activity won't be re-started when adding the token to the history.
However, if the user goes back and forward through the history, the performance problem would still be there (because then, the events will be fired again).
In our app we need to check if the data is saved when we are in a particular place before navigating away from it. So the user should be able to negate a browser back button request. But by the time that the history value change event is received the url has already been changed. The History class doesn't seem to have a way to restore the url back. Anybody have any ideas?
In GWT 2.1 you get Activities and Places. And activity has a maystop method, which is exactly what you want, if I understand you correctly.
Use a window.onunload or window.onbeforeunload javascript callback to confrim/save state.
onbeforeunload example
I haven't actually implemented this behavior yet, but here is my plan and maybe it will work for you.
1) Each time you receive an onHistoryChanged event and decide to allow it, save the current historyToken in an instance variable somewhere.
2) Keep track of activity on the page that should block navigation. Use a data structure that can keep track of multiple activities, like multiple file uploads, multiple edits, etc.
3) When you receive a new onHistoryChanged event, if your data structure from #2 indicates that it's not safe to navigate, avoid changing the page and restore the historyToken that you saved in #1. I'm assuming that you can do this either by:
a) Calling History.newItem(oldHistoryToken, false) or
b) Calling History.newItem(oldHistoryToken, true) and keeping a flag to force the next onHistoryChanged to be ignored.
Again, I haven't actually implemented this so let me know how it works out.
If you have links that allow the user to leave the app and you want to prevent that as well, you'll need to also add an onbeforeunload.
Have a look at the PlaceManagerImpl class from the gwt-platform framework. Especially the onValueChange() method and the methods dealing with the onLeaveQuestion field.
Hope that helps.
In this issue report, t.broyer explains in his comment that such behavior was planned during design of Places framework. The most important part is:
mayStop was a mistake, or it should have only been called when unloading the app, not for internal navigation within the app.
So probably it's better to not use it at all...
Preface:
If you don't care about the preface, skip down to the section marked "Question."
Hi,
Recently my company has upgraded to the latest version of WatiN for its test automation framework. We upgraded to avoid a problem where interacting with a select list would cause an ACCSES DENIED error. This error seems to be a product of the fact that our web application reloads the page it is on (which sits in a frame which sits in a frameset) with new fields after certain select lists options are selected. It could also be that our framework, which wraps around WatiN, often does actions on the same SelectList after the page refresh (I'm still looking into this, I'm new to the framework).
The new version of WatiN does solve the ACCESS DENIED error, but also seems to stop select lists from firing the action that causes the page to reload w/ its new options. In fact, if you use WatiN to make the selection, the select list won't work correctly, even if manually interacted with, until the page has been forced to refresh.
Question:
When selecting an option in a SelectList using the newest WatiN code, the event that causes our web app's page to reload with new fields/values does not execute. What are some possibilities that could cause this?
The term i've seen used most often to describe the refreshing that occurs when our select lists are used is "double post-back".
Many thanks,
Chad
This is part of the new WatiN code. The new code, if you look into the SelectList class has comments about the fact that it has been changed so that these events don't exactly fire. It says something along the lines of "you may need to use a key press or other event to get a select list to fire its events".
This didn't work for me so we went back to the old code.
One thing that has helped is wrapping calls to the select list w/ a try/catch(System.UnauthorizedAccess e) and then doing a .Refresh on the select list object. Afterwards, the call can be retried and it seems to work pretty well.