odata4j requests metadata too many times - android

I use the odata4j library to access a WCF Data Service.
This is how I call a Service Method from my Android code:
OQueryRequest<OEntity> l = consumer.getEntities("GetDataList")
.custom("dataId", String.format("'%s'", actualData.ID))
.orderBy("Name").skip(0).top(200);
I checked it with WireShark, and I see that every method call is preceded with 2 calls of metadata information request:
Why? Are they essential? The metadata information is quite heavy, it shouldn't request is every time (not to mention 2 times).
What should I do to prevent odata4j from requesting metadata information so many times?

I found in the source code where the 'extra' request happens (in odata4j/odata4j-core/src/main/java/org/odata4j/consumer/AbstractODataConsumer.java ):
#Override
public EdmEntitySet findEdmEntitySet(String entitySetName) {
EdmEntitySet rt = super.findEdmEntitySet(entitySetName);
if (rt == null && delegate != EdmDataServices.EMPTY) {
refreshDelegate();
rt = super.findEdmEntitySet(entitySetName);
}
return rt;
}
It seems that if the entity set can't be found, the consumer creates an extra roundtrip to the server to get the metadata again (by calling refreshDelegate()):
private void refreshDelegate() {
ODataClientRequest request = ODataClientRequest.get(AbstractODataConsumer.this.getServiceRootUri() + "$metadata");
try {
delegate = AbstractODataConsumer.this.getClient().getMetadata(request);
} catch (ODataProducerException e) {
// to support services that do not expose metadata information
delegate = EdmDataServices.EMPTY;
}
}
I don't quite understand why: maybe it assumes that the server has changed and a new version of the metadata is available so it tries again.
If it fails then it tries to find a function with the given name.
Personally I don't consider this very effective unless the server side is so volatile that it changes between calls.
So, if you have no changing metadata on the server, it is safe to remove the check for the entitySet and let it return as a null:
#Override
public EdmEntitySet findEdmEntitySet(String entitySetName) {
EdmEntitySet rt = super.findEdmEntitySet(entitySetName);
//if (rt == null && delegate != EdmDataServices.EMPTY) {
// refreshDelegate();
// rt = super.findEdmEntitySet(entitySetName);
//}
return rt; //if it is null, then the search for a function will commence
}

Related

Read value returned in CompletableFuture

A function from some SDK is returning me a CompletableFuture. How can I read the value properly once it's reached.
My Code:
CompletableFuture<Web3ClientVersion> web3clientCompletableFuture;
web3clientCompletableFuture = web3jNode.web3ClientVersion().sendAsync();
sendAsync() Code (In SDK):
public CompletableFuture<T> sendAsync() {
return web3jService.sendAsync(this, responseType);
}
I can access the returned data using get(), but that would make the whole process syncronus and block UI.
I've checked the functions signatures on Android API Reference, like:
thenApply(Function<? super T, ? extends U> fn)
handle(BiFunction<? super T, Throwable, ? extends U> fn)
But seems I require some code examples.
[Note: I'm not so familiar with lambda]
Here is a tutorial that has examples that show you how to use these powerful methods of CompletableFuture. You are right you want to use thenApply() if you have to return value after you process the future. But if you simply want to process the future and not return anything, you should use thenAccept() and thenRun(). There are other methods listed with examples as well.
Here is an example that simply returns a CompletableFuture of type integer:
CompletableFuture<Integer> mynumber = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
mynumber = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return 4 * 4;
});
}
Here arg is the result(CompletableFuture) from the above step, and in your case the data you are receiving from the SDK. You are attaching a callback method(thenApply()) and do what ever you would like to do with it. Depending on your implementation, you can attach multiple thenApply(). Here I am calling a method that will take the result and do some computation with it.
CompletableFuture<Integer> willdoStuff = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
willdoStuff = mynumber.thenApply(arg -> {
compute(arg);
return arg / 2;
});
}
public void compute(int someInt){
Toast.makeText(getApplicationContext(), "The result of the computation is" + someInt, Toast.LENGTH_LONG).show();
}
Just comment out the sleep code to execute this code in the main thread.
The Lambda function is simply input and output, the arguments before {} being the input and the statement within the {}, which is actually a function that does something with the arguments(input). You might want to ask different question in regards to that.

IHE and HL7. PCD-01 ACK

I'm trying to get data from a monitor to an Android application and I've took the IHE - PCD-01 transaction as a model.
The scheme is simple, is based on achieve the interconnection between the monitor and the tablet, where the monitor sends constantly information and the application is listening.
But what I don't understand is if I need an ACK or not after every message. Does anyone can help me with this?
TL;DR yes, nothing special here, support the usual HL7 ACK/NACK driven by MSH-15, MSH-16 fields. ACK-ing everything by default is "better safe then sorry"
The document "IHE Patient Care Device (PCD), Technical Framework, Volume 2 (PCD TF-2) Transactions, Revision 1.0 - Final Text, August 12, 2011" available at http://www.ihe.net/technical_framework/upload/ihe_pcd_tf_vol2_ft_2011-08-12.pdf says
..The common static definition of the HL7 acknowledgement (ACK) message is described in Appendix G, "HL7 Implementation Notes"..
which says
G.1 Network Guidelines
The HL7 2.6 standard does not define a network communications protocol. Beginning with HL7 2.2, the definitions of lower layer protocols were moved to the Implementation Guide, but are not HL7 requirements. The IHE Framework makes these recommendations:
Applications shall use the Minimal Lower Layer Protocol defined in Appendix C of the HL7 Implementation Guide.
An application that wants to send a message (initiate a transaction) will initiate a network connection to start the transaction. The receiver application will respond with an acknowledgement or response to query but will not initiate new transactions on this network connection
G.1.1 Acknowledgment Modes
ACKNOWLEDGMENT MESSAGES
Acknowledgment messages may be defined on an application basis. However the simple general acknowledgment message (ACK) may be used where the application does not define a special message (application level acknowledgment) and in other cases as described in Section 2.9, "Message Processing Rules".
The IHE PCD transaction PCD-03 supports „enhanced mode‟ acknowledgements. See discussion under PCD-03 Transactions as well as in B.1 MSH – Message Header Segment and B.2 MSA – Message Acknowledgement Segment
and document "Health Level Seven, Version 2.6 © 2007, Chapter 2: Control" coming from the "HL7 Messaging Standard Version 2.6" package which can be downloaded from http://www.hl7.org/implement/standards/product_brief.cfm?product_id=185 describes the accept and validate behavior in
2.9.2 Message response using the original processing rules
..too long to quote..
2.9.3 Response using enhanced acknowledgement
..too long to quote..
depending on the values of MSH-15 Accept Acknowledgement Type and MSH-16 Application Acknowledgment Type fields in the HL7 message
The above chapters from the HL7 standard contain what you want to read and implement/support.
EDIT:
Simply put, in HL7 protocol in every message sent the sender may request an ACK receipt by flagging appropriate fields in the message header segment. IHE does not remove this rule and does not enforce any other but enables any other convention to be defined on an application basis. Correct expected behavior is defined by the HL7 specification and in order to get it right and create a conforming implementation (without hidden surprises for your 3rd parties) you may need to read it several times (see also Stack Overflow: How can I make my system HL7 certified?)
For example this is how HAPI library handles the ACKing, snippet comes from http://sourceforge.net/p/hl7api/code/764/tree/tags/Root_REL_1_2/hapi-mvn/hapi-base/src/main/java/ca/uhn/hl7v2/protocol/impl/ProcessorImpl.java
/**
* #see ca.uhn.hl7v2.protocol.Processor#cycle(boolean)
*/
public void cycle(boolean expectingAck) throws HL7Exception {
log.debug("In cycle({})", expectingAck);
cleanReservations();
cleanAcceptAcks();
cleanReservedMessages();
Transportable in = null;
try {
if (expectingAck) {
in = tryReceive(myContext.getLocallyDrivenTransportLayer());
} else {
in = tryReceive(myContext.getRemotelyDrivenTransportLayer());
}
} catch (TransportException e) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {}
throw e;
}
// log
if (in != null) {
log.debug("Received message: {}", in.getMessage());
} else {
log.debug("Received no message");
}
// If we have a message, handle it
if (in != null) {
String acceptAckNeeded = null;
// String appAckNeeded = null;
String ackCode = null;
String ackId = null;
try {
String[] fieldPaths = {"MSH-15", "MSH-16", "MSA-1", "MSA-2"};
String[] fields = PreParser.getFields(in.getMessage(), fieldPaths);
acceptAckNeeded = fields[0];
// appAckNeeded = fields[1];
ackCode = fields[2];
ackId = fields[3];
} catch (HL7Exception e) {
log.warn("Failed to parse accept ack fields in incoming message", e);
}
if (ackId != null && ackCode != null && ackCode.startsWith("C")) {
long expiryTime = System.currentTimeMillis() + 1000 * 60;
myAcceptAcks.put(ackId, new ExpiringTransportable(in, expiryTime));
} else {
AcceptAcknowledger.AcceptACK ack = AcceptAcknowledger.validate(getContext(), in);
if ((acceptAckNeeded != null && acceptAckNeeded.equals(AL))
|| (acceptAckNeeded != null && acceptAckNeeded.equals(ER) && !ack.isAcceptable())
|| (acceptAckNeeded != null && acceptAckNeeded.equals(SU) && ack.isAcceptable())) {
trySend(myContext.getRemotelyDrivenTransportLayer(), ack.getMessage());
}
if (ack.isAcceptable()) {
if (isReserved(ackId)) {
log.debug("Received expected ACK message with ACK ID: {}", ackId);
removeReservation(ackId);
long expiryTime = System.currentTimeMillis() + 1000 * 60 * 5;
myAvailableMessages.put(ackId, new ExpiringTransportable(in, expiryTime));
} else {
log.debug("Sending message to router");
Transportable out = myContext.getRouter().processMessage(in);
sendAppResponse(out);
}
} else {
// TODO: should we do something more here? Might be nice to
// allow a configurable handler for this situation
log.warn("Incoming message was not acceptable");
}
}
} else {
String transport = expectingAck ? " Locally driven " : "Remotely driven";
log.debug("{} TransportLayer.receive() returned null.", transport);
}
sleepIfNeeded();
log.debug("Exiting cycle()");
}
Thanks for your answer :)
of course that it is better to use an ACK to make sure if the receiver is getting the message but what I wanted to know if it was mandatory or not using the PCD-01 transaction.
I've read your documents and what I've understood is that the use of ACK depends on the MSH-15 and MSH-16 fields content, but with the following information:
An application that wants to send a message (initiate a transaction) will initiate a network connection to start the transaction. The receiver application will respond with an acknowledgement or response to query but will not initiate new transactions on this network connection
I understand that the ACK is only at the beginning of the connection not after every message, is it right?

Google Plus Single Sign On Server Flow - Google_AuthException Error fetching OAuth2 access token, message: 'invalid_grant'

UPDATE 27th January 2013
I have now resolved this, Please check the accepted answer.
I am having trouble to get my refresh token and my access token when using the server side flow between my Android Application and my PHP server.
So I have managed to get my One Time Code by using the below:
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
Bundle appActivities = new Bundle();
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
"http://schemas.google.com/AddActivity");
String scopes = "oauth2:server:client_id:" + SERVER_CLIENT_ID +
":api_scope:" + SCOPE_STRING;
try {
code = GoogleAuthUtil.getToken(
OneTimeCodeActivity.this, // Context context
mPlusClient.getAccountName(), // String accountName
scopes, // String scope
appActivities // Bundle bundle
);
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
System.out.println(transientEx.printStactTrace());
return "Error";
} catch (UserRecoverableAuthException e) {
// Recover
code = null;
System.out.println(e.printStackTrace());
OneTimeCodeActivity.this.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
System.out.println(authEx.printStackTrace());
return "Error";
} catch (Exception e) {
System.out.println(authEx.printStackTrace());
}
}
Which will then store the token in the variable "code" and I call up the async task as
task.execute();
The code above will always bring up a popup message and throw UserRecoverableAuthException Need Permission that requires the user to grant offline access, which means the above will need to be called twice to retrieve the code and store it in "code"
I am now trying to send this across to my server which is implemented in PHP.
I have used the quick start https://developers.google.com/+/quickstart/php and managed to get that working.
In here, there is a sample signin.php
In here and according to the documentation this already implements a One Time Authorisation Server Side Flow.
So now my problem is sending this One Time Code to the server.
I used the photohunt Android Auth example for this located here.
https://github.com/googleplus/gplus-photohunt-client-android/blob/master/src/com/google/plus/samples/photohunt/auth/AuthUtil.java
I used the "authorization" method of the code and called up signin.php/connect through a post method shown below
$app->post('/connect', function (Request $request) use ($app, $client) {
$token = $app['session']->get('token');
if (empty($token)) {
// Ensure that this is no request forgery going on, and that the user
// sending us this connect request is the user that was supposed to.
if ($request->get('state') != ($app['session']->get('state'))) {
return new Response('Invalid state parameter', 401);
}
// Normally the state would be a one-time use token, however in our
// simple case, we want a user to be able to connect and disconnect
// without reloading the page. Thus, for demonstration, we don't
// implement this best practice.
//$app['session']->set('state', '');
$code = $request->getContent();
// Exchange the OAuth 2.0 authorization code for user credentials.
$client->authenticate($code);
$token = json_decode($client->getAccessToken());
// You can read the Google user ID in the ID token.
// "sub" represents the ID token subscriber which in our case
// is the user ID. This sample does not use the user ID.
$attributes = $client->verifyIdToken($token->id_token, CLIENT_ID)
->getAttributes();
$gplus_id = $attributes["payload"]["sub"];
// Store the token in the session for later use.
$app['session']->set('token', json_encode($token));
$response = 'Successfully connected with token: ' . print_r($token, true);
}
return new Response($response, 200);
});
Now when I send the code using the above implementation, I get an 500 messages that says the below
Google_AuthException Error fetching OAuth2 access token, message: 'invalid_grant'
in ../vendor/google/google-api-php-client/src/auth/Google_OAuth2.php line 115
at Google_OAuth2->authenticate(array('scope' => 'https://www.googleapis.com/auth/plus.login'), '{ "token":"xxxxxxxx"}') in ../vendor/google/google-api-php-client/src/Google_Client.php line 131
at Google_Client->authenticate('{ "token":"xxxxxxx"}') in ../signin.php line 99
at {closure}(object(Request))
at call_user_func_array(object(Closure), array(object(Request))) in ../vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php line 117
at HttpKernel->handleRaw(object(Request), '1') in ../vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php line 61
at HttpKernel->handle(object(Request), '1', true) in ../vendor/silex/silex/src/Silex/Application.php line 504
at Application->handle(object(Request)) in ../vendor/silex/silex/src/Silex/Application.php line 481
at Application->run() in ../signin.php line 139
Funny enough I have had to worked once where I did receive a 200, but I cannot recreate it.
So I know I have definitely got the implementation wrong, but I have no clue on how to send it and get my refresh token. I can't find anywhere on the web that explains this. Is someone able to help me please.
UPDATE 16 Jan 2014
Using https://www.googleapis.com/oauth2/v1/tokeninfo?access_token= I can see that the token being produced from getToken is valid and is indeed valid for 1 hour.
I can confirm the json formation is correct by changing the way I am inputting into the Post request and if I don't do it properly I get a total failure.
Now I am going deeper into the php and look at this section Google_OAuth2.php line 115 where it is breaking it is throwing a Google_AuthException. The code is below and this is provided in the quick starter pack
/**
* #param $service
* #param string|null $code
* #throws Google_AuthException
* #return string
*/
public function authenticate($service, $code = null) {
if (!$code && isset($_GET['code'])) {
$code = $_GET['code'];
}
if ($code) {
// We got here from the redirect from a successful authorization grant, fetch the access token
$request = Google_Client::$io->makeRequest(new Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), array(
'code' => $code,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->redirectUri,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret
)));
if ($request->getResponseHttpCode() == 200) {
$this->setAccessToken($request->getResponseBody());
$this->token['created'] = time();
return $this->getAccessToken();
} else {
$response = $request->getResponseBody();
$decodedResponse = json_decode($response, true);
if ($decodedResponse != null && $decodedResponse['error']) {
$response = $decodedResponse['error'];
}
throw new Google_AuthException("Error fetching OAuth2 access token, message: '$response'", $request->getResponseHttpCode());
}
}
$authUrl = $this->createAuthUrl($service['scope']);
header('Location: ' . $authUrl);
return true;
}
I edit the code above to make sure the code, the client id and secret were correct and they were. So that is where I am now, I don't think it is scope issues as well as I hard coded it in the client setup and still does not work. Not too sure.
UPDATE 23rd January
OK, I think it is a time issue. I used https://developers.google.com/+/photohunt/android and base my design on the BaseActivity in the Photohunt using the AuthUtil, and I get invalid grant on my server. How do I move the time back on my server in code. I read somewhere I can do time() - 10 somewhere but not sure where...
It sounds like you may be sending the same authorization code multiple times. On Android GoogleAuthUtil.getToken() caches any tokens that it retrieves including authorization codes.
If you ask for a second code without invalidating the previous code, GoogleAuthUtil will return the same code. When you try to exchange a code on your server which has already been exchanged you get the invalid_grant error. My advice would be to invalidate the token immediately after you retrieve it (even if you fail to exchange the code, you are better off getting a new one than retrying with the old one).
code = GoogleAuthUtil.getToken(
OneTimeCodeActivity.this, // Context context
mPlusClient.getAccountName(), // String accountName
scopes, // String scope
appActivities // Bundle bundle
);
GoogleAuthUtil.invalidateToken(
OneTimeCodeActivity.this,
code
);
invalid_grant can be returned for other reasons, but my guess is that caching is causing your problem since you said it worked the first time.
This issue is now resolved. This was due to the implementation on the One Time Code exchange with the server
As specified in the my issue above, I used the photohunt example to do the exchange with my server. The Android code can be found on the below link
https://github.com/googleplus/gplus-photohunt-client-android/blob/master/src/com/google/plus/samples/photohunt/auth/AuthUtil.java
One line 44 it reads this
byte[] postBody = String.format(ACCESS_TOKEN_JSON, sAccessToken).getBytes();
This will only work if on the server side you handle the JSON. I did not.
When calling up $client->authenticate($code); in php, $code had a JSON string and therefore when calling https://accounts.google.com/o/oauth2/token the authorization code was wrong.
So it was easy as I was not sending the code in the right format.
I found this out when digging and testing https://accounts.google.com/o/oauth2/token and created a manual cURL to test the token.
As provided in the Google+ API it was stated that all examples included a One Time Code exchange, but I think the code across all platform are not consistent and one has to double check themselve to make sure everything flows correctly, which was my mistake.

JSON experimental from Android App

On Android I am able to upload an object Ok. But when I try to download it, I get the following error on getObject.executeMediaAndDownloadTo(out).
java.lang.IllegalArgumentException: Type must be in the 'maintype/subtype; parameter=value' format
Code is from the Google example:
Storage.Objects.Get getObject = storage.objects().get("bucket", "myObject");
if (getMetadata == true) {
getObject.setAlt("json"); // Temporary workaround.
StorageObject object = getObject.execute();
} else {
// Downloading data.
out = new ByteArrayOutputStream();
// If you're not in AppEngine, download the whole thing in one request, if possible.
// NOTE: As of right now, this will not retry on retryable failure.
// http://code.google.com/p/google-api-java-client/issues/detail?id=579
getObject.getMediaHttpDownloader().setDirectDownloadEnabled(true);
getObject.executeMediaAndDownloadTo(out);
}

WCF REST service 400 Bad Request

I have WCF RESTful service and Android client.
Server replies with 400 when I do bigger request. It seems that I have 65k limit issue like
in here or in other million posts on same problem.
However, I can't seem to be able to fix it. Here is how my web.config looks
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="myEndpoint" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="1000000" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
Here is code example of service function:
[WebInvoke(UriTemplate = "/trips/{TripId}/inspection", Method = "POST")]
[Description("Used on mobile devices to submit inspections to server")]
public void PostTripInspection(string tripId, Inspection inspection)
{
return;
}
Here is code inside my Web project which hosts WCF (Global.asax.cs)
private static void RegisterRoutes()
{
// Setup URL's for each customer
using (var cmc = new CoreModelContext())
{
foreach (var account in cmc.Accounts.Where(aa => aa.IsActive).ToList())
{
RouteTable.Routes.Add(
new ServiceRoute(
account.AccountId + "/mobile", new WebServiceHostFactory(), typeof(MobileService)));
}
}
}
From what I understand Java HttpClient doesn't impose any limits so it's on WCF side. Any pointers on how to solve this issue or how to intercept message in WCF?
EDIT 2:
This is what trace shows. And when I modigy standardEndpoint it doesn't help...
Forgive me if you've seen this link (Similar StackOverflow Question):
By default the WCF Transport is
limited to sending messages at 65K. If
you want to send larger you need to
enable Streaming Transfer Mode and
you need to increase the size of
MaxReceivedMessageSize, which is there
just as a guard to prevent someone
killing your server by uploading a
massive file.
So, you can do this using binding
configuration or you can do it in
code. Here is one way to do it in
code:
var endpoint = ((HttpEndpoint)host.Description.Endpoints[0]); //Assuming one endpoint
endpoint.TransferMode = TransferMode.Streamed;
endpoint.MaxReceivedMessageSize = 1024 * 1024 * 10; // Allow files up to 10MB
You don't need to use streaming in this case - all you need to do is to increase the maxReceivedMessageSize quota on the standard webHttpEndpoint:
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name=""
helpEnabled="true"
automaticFormatSelectionEnabled="true"
maxReceivedMessageSize="1000000"/>
</webHttpEndpoint>
</standardEndpoints>
Update: if the config change didn't work (I don't know why), you can try increasing it in code. By using a custom service host factory, you get a reference to the endpoint object and you can increase the quota there. The code below shows one such a factory (you'll need to update the RegisterRoute code to use this new factory):
public class MyWebServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return base.CreateServiceHost(serviceType, baseAddresses);
}
class MyWebServiceHost : WebServiceHost
{
public MyWebServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
base.OnOpening();
foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
{
if (!endpoint.IsSystemEndpoint)
{
Binding binding = endpoint.Binding;
if (binding is WebHttpBinding)
{
((WebHttpBinding)binding).MaxReceivedMessageSize = 1000000;
}
else
{
CustomBinding custom = binding as CustomBinding;
if (custom == null)
{
custom = new CustomBinding(binding);
}
custom.Elements.Find<HttpTransportBindingElement>().MaxReceivedMessageSize = 1000000;
}
}
}
}
}
}

Categories

Resources