Current filter:
                                You should refresh the page.
                                  • Hello,

                                    We are changing our JsonDataSource at runtime, in a report, using the Parameters, sent by the user, to retrieve a json.
                                    What we are doing is the follow: Get the Uri in the UriJsonSource; Retrieve the json with the uri and parameters; Set the JsonSource with a CustomJsonSource(json). When we fill the DataSource our CustomJsonSource is replaced with the old UriJsonSource by the this.Connection.GetJsonSource().

                                    Searching for an answer, i've found this ticket, but no clue to solve our case. I also read this.
                                    Sending some prints for better understanding .

                                1 Solution

                                Creation Date Importance Sort by

                                Hi
                                >>We are changing our JsonDataSource at runtime, in a report
                                Changing JsonDataSource.JsonSource directly is not entirely correct since once a connection is established, it's cached internally. To change connection settings on the fly, I suggest that you implement and register a special service called IJsonSourceCustomizationService. Please see the following code that illustrates how to use it:

                                [C#]
                                using DevExpress.XtraPrinting.Native; MyReport1 report = new MyReport1(); report.ReplaceService<IJsonSourceCustomizationService>(new MyJsonCustomizationService()); report.CreateDocument(); public class MyJsonCustomizationService : IJsonSourceCustomizationService { public JsonSourceBase CustomizeJsonSource(JsonDataSource jsonDataSource) { return new DevExpress.DataAccess.Json.UriJsonSource(...)); } }

                                Try this approach and let know if it works for you.

                                Regards,
                                Yaroslav

                                Show all comments
                                • Customer71556 07.29.2019

                                  Hello.

                                  I've found this solution in this ticket, but it didn't worked for me. The IJsonSourceCustomizationService  is in the Fill method, but was injecting just in the Designer's Preview mode. When called by WebDocumentViewer the service was null. We made a change to inject the service inside our Fill, direct inside RestDataSource, and it worked (so far). The changes include remove the RootElement before the "base.Fill(params)" and then set back at the end of our Fill. I personally didn't like this.

                                  [C#]
                                  private void Fill(IEnumerable<IParameter> sourceParameters, bool isDesign) { var uriSource = this.JsonSource as UriJsonSource; var rootElement = ""; if (uriSource != null) { var jsonDataSourceType = DataSourceType.Deserialize<JsonDataSourceType>(uriSource.RootElement); // Save the RootElement; rootElement = uriSource.RootElement; var uri = GetRequestUri(jsonDataSourceType, sourceParameters); JsonSource = new CustomJsonSource(PerformRequest(uri, jsonDataSourceType)); // Inject the IJsonSourceCustomizationService; this.ReplaceService<IJsonSourceCustomizationService>(new ReportJsonCustomizationService()); // Set RootElement null; uriSource.RootElement = null; } try { base.Fill(sourceParameters); } catch (TargetInvocationException ex) { throw ex.InnerException; } finally { // Set back the UriJsonSource and the RootElement; if (uriSource != null) { JsonSource = uriSource; JsonSource.RootElement = rootElement; } } }

                                  In the ReportJsonCustomizationService.CustomizeJsonSource we just return jsonDataSource.JsonSource to override the Connection.GetJsonSource, as expected.

                                  So far, so good. But it doesn't work: When printing the report i get a Null Reference because it can't find the data member and throws an exception. I'm sending a print of this case.

                                • Customer71556 07.29.2019

                                  After i submit the Report for the first time it's throws the error mentioned above, but it works after this first try. If i set this.Connection to null, in the JsonDataSource.Fill, also works. As you said, "cached internally", this error may be related to an earlier thread trying to resolve.

                                • Yaroslav (DevExpress Support) 07.29.2019

                                  >>When called by WebDocumentViewer the service was null
                                  Would you please clarify if you're using the Web End-User Report Designer? According to the documentation, PreviewReportCustomizationService is only used by the designer and not the document viewer. There is not much you can gain from this service if you're using the standalone WebDocumentViewer anyway as you can always bind it to an XtraReport instance. In turn, you can use this instance to replace IJsonSourceCustomizationService with your custom implementation.
                                  As for the issue you're discussing, it certainly should not be required to manipulate with the RootElement to get things working. If for any reason this above code approach does not work for you, please provide us with a sample project where changing the JsonDataSource connection results in the "Invalid Data Member" error. Use a local file URI to prevent the need of creating a dummy Web API service.

                                  Regards,
                                  Yaroslav

                                • Customer71556 07.29.2019

                                  To make a sample of this case will take a while.
                                  Some of our users make report, DevExpress().ReportDesigner, others just view them, DevExpress().WebDocumentViewer. We need a solution for both scenarios.
                                  Is there a way to disable this "cached report"? I can confirm our approach was working in the last version.

                                • Yaroslav (DevExpress Support) 07.30.2019

                                  There is no way to prevent caching. To change JsonDataSource original connection parameters prior to its filling, use IJsonSourceCustomizationService. This is the service we specifically designed for this task.
                                  In the End-User Report Designer that does not provide direct access to a report instance being edited, it's necessary to use the solution I described in the Multi-tenant web report implementation where reports and data are filtered by account thread.
                                  Doing the same but in the case of the WebDocumentViewer should not require any extra handling.

                                  If for any reason that service does not work for you, we'd like to see a sample project illustrating the exact scenario you're trying to accomplish. There is no rush. I'll keep this ticket open for as long as it's needed.
                                  Thank you for your time and cooperation in advance.

                                  Regards,
                                  Yaroslav

                                • Customer71556 07.30.2019

                                  Thank you for your time.
                                  Over a few tests i noticed the "Invalid Data Member" occurs if our custom JsonDataSource doesn't have the data members in it's innerList (the last few lines in function bellow. It's in DevExpress.DataAccess.Json.JsonDataSource)

                                  [C#]
                                  public override void Fill(IEnumerable<IParameter> sourceParameters) { IJsonSourceCustomizationService service = this.GetService<IJsonSourceCustomizationService>(); if (service != null) this.AssignConnection(new JsonDataConnection(service.CustomizeJsonSource(this)) { Name = this.ConnectionName }); JsonSourceBase jsonSource = this.Connection?.GetJsonSource(); if (jsonSource == null) return; Type type = (Type) null; if (jsonSource.Owner == null) jsonSource.Owner = this; string jsonString = jsonSource.GetJsonString(); if (string.IsNullOrEmpty(jsonString)) return; string rootElement = !string.IsNullOrEmpty(this.RootElement) ? this.RootElement : (!string.IsNullOrEmpty(jsonSource.RootElement) ? jsonSource.RootElement : string.Empty); if (this.Schema == null) { type = new JsonLoaderHelper().DetectJsonSchema(jsonString, rootElement); this.Schema = this.LoadSchema(type); } if (!string.IsNullOrEmpty(rootElement)) { JObject jobject = JTokenBase.Wrap(JsonLoaderHelper.DeserializeObject(jsonString)) as JObject; if (jobject == null) throw new InvalidOperationException("Can not select an element inside an array"); object obj = jobject.SelectToken(rootElement); if (obj == null) return; jsonString = obj.ToString(); } JsonLoaderHelper jsonLoaderHelper1 = new JsonLoaderHelper(rootElement, this.Schema); JsonLoaderHelper jsonLoaderHelper2 = jsonLoaderHelper1; string json = jsonString; Type objectType = type; if ((object) objectType == null) objectType = this.jsonType; this.createdObject = jsonLoaderHelper2.CreateObject(json, objectType); IEnumerable<object> createdObject = this.createdObject as IEnumerable<object>; if (createdObject != null) this.innerList = (IList) createdObject.ToList<object>(); else this.innerList = (IList) new object[1] { this.createdObject }; this.jsonType = jsonLoaderHelper1.JsonType; }

                                  What is happening: I change my UriJsonSource to CustomJsonSource. When my customSource enters in the Fill (code above), it has a rootElement, don't find a jobject.SelectToken() and returns before set the innerList, than it crashes because my customSource doesn't have the dataMembers.
                                  Solution: Set IJsonSourceCustomizationService  (code bellow) to remove the rootElement, than load it's innerList. Back in our Fill (code in my previous comment) and set back the DataSource to UriJsonSource and the rootElement. This way we can load a customDataSource with our dataMember.

                                  [C#]
                                  public JsonSourceBase CustomizeJsonSource(JsonDataSource jsonDataSource) { jsonDataSource.JsonSource.RootElement = null; return jsonDataSource.JsonSource; }
                                • Yaroslav (DevExpress Support) 07.31.2019

                                  Thank you for your explanation. The way I understand it, you're changing the RootElement property because not only the connection of your JsonDataSource is different, but its schema as well. This is quite unexpected since almost any report layout is designed against a particular schema. Changing it will ultimately break control bindings. Anyway, if you're prepared to handle this and things are working for you now, I'm happy to hear that.
                                  Should you need to discuss the issue further, feel free to reactivate this ticket. Any sample project illustrating the real scenario you're trying to solve would be greatly appreciated.

                                  Regards,
                                  Yaroslav