What is the best approach to validate the GRPC input request? In the below example, we need to validate both fields, as these are required fields.
For example:
message AudienceRequest {
int32 id = 1;
string name = 1;
}
Related
I have one proto file for gRPC server
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string othermessage = 1;
string message = 2;
string othermessage2 = 3;
}
My client don't need the fields othermessage and othermessage2. I make other proto file for client
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 2;
}
It works, but is it correct?
I see the following advantages: the client receive only the necessary data, the client's proto-file is not overloaded. For example, in sql we get only the required fields.
Maybe it's more efficient? Are all fields transmitted over the network or only the requested one?
I used the article Analyzing gRPC messages using Wireshark to validate fields sent over the network. All fields are sent. Therefore, using truncated proto files does not increase efficiency.
As a result, we can use the truncated proto file on the client, if it contains non-breaking differences, by analogy with non-breaking changes. This does not increase performance and can only be used to reduce the proto file on the client side.
let's say i have a proto file like this. can I define service like this
rpc SayHello () returns (Response) {} //service has no input
rpc SayHello (Request1,Request2) returns (Response) {}//service has two inputs
//.proto file
syntax = "proto3";
service Greeter{
rpc SayHello (Request) returns (Response) {}
}
message Request{
string request = 1;
}
message Response{
string response = 1;
}
gRPC service methods have exactly one input message and exactly one output message. Typically, these messages are used as input and output to only one method. This is on purpose, as it allows easily adding new parameters later (to the messages) while maintaining backward compatibility.
If you don't want any input or output parameters, you can use the well-known proto google.protobuf.Empty. However, this is discouraged as it prevents you from adding parameters to the method in the future. Instead, you would be encouraged to follow the normal practice of having a message for the request, but simply with no contents:
service Greeter {
rpc SayHello (SayHelloRequest) returns (SayHelloResponse) {}
}
message SayHelloRequest {} // service has no input
Similarly, if you want two request parameters, just include both in the request message:
message SayHelloRequest { // service has two inputs
string request = 1;
string anotherRequestParam = 2;
}
I am trying to integrate Paytm in an ASP.NET website. Payment processing is going well, but when a transaction is completed, it redirects to my "callbackurl" page.
Here I don`t know how to read the response of the transaction. I checked my callback page using inspect element but there was no json or any error message or message in console.
You can call this function during your page load event of callback url. If checksumhash is matched then you can call additional parameters.
String merchantKey = "****************"; // Replace the with the Merchant Key provided by Paytm at the time of registration.
Dictionary<string, string> parameters = new Dictionary<string, string>();
string paytmChecksum = "";
foreach (string key in Request.Form.Keys)
{
parameters.Add(key.Trim(), Request.Form[key].Trim());
}
if (parameters.ContainsKey("CHECKSUMHASH"))
{
paytmChecksum = parameters["CHECKSUMHASH"];
parameters.Remove("CHECKSUMHASH");
}
if (CheckSum.verifyCheckSum(merchantKey, parameters, paytmChecksum))
{
lbl_status.Text = parameters["STATUS"];
Response.Write("Checksum Matched");
}
else
{
Response.Write("Checksum MisMatch");
}
I have a web page that uses a WCF service. Multiple users maybe using the web page at any one time and therefore making requests to the WCF service which is on a remote machine.
Each user on the web page gets a unique ID, I want to add this unique ID to the request header of each request made by that user.
So far I have created the following code which correctly adds a header to the WCF message.
public class HeaderIdPusher : IClientMessageInspector
{
private static readonly string _balancerKey = "balancerId";
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
Guid userId = Guid.NewGuid();
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (string.IsNullOrEmpty(httpRequestMessage.Headers[_balancerKey]))
{
httpRequestMessage.Headers[_balancerKey] = userId.ToString();
}
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers.Add(_balancerKey, userId.ToString());
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
However I am no stuck because I can't get the ID to persist between requests. You can see here that at the moment I am generating an ID for each request, however I can't store this in the Session of the page the user is on because the HttpContext.Current is null. Is there another way of storing this? Is there another way of passing in the HttpContext of the user on my web page?
The problem is discussed here:
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/27896125-b61e-42bd-a1b0-e6da5c23e6fc
Essentially WCF doesn't have sessions, as you could pass anything you wanted as a parameter (in this case, your Unique ID) and handle it any way you wanted in your implementation.
After much hacking I found a solution, it isn't great but it works.
In the ASP.NET page before I create the WCF service instance I create an address header and endpoint:
AddressHeader header = AddressHeader.CreateAddressHeader("MyKey", "http://www.w3.org/2005/08/addressing", "MyValue");
EndpointAddress endpoint = new EndpointAddress(new Uri("http://www.myservice.com/service"), header);
Then I create an instance of the service passing in the endpoint:
using (WcfService service = new WcfService(_configName,endpoint ))
{
}
This gets the data into the WCF service, then in the HeaderIdPusher : IClientMessageInspector detailed above I pull the header value out:
public class HeaderIdPusher : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string id = "Not found";
if(channel.RemoteAddress.Headers.Any(x=>x.Name == "MyKey"))
{
id = channel.RemoteAddress.Headers.First(x => x.Name == "MyKey").GetValue<string>();
}
This solution isn't ideal and it puts extra data into the SOAP message but it is the only way I have found of sharing data from the ASP.NET page with the WCF process.
I want to localize Web Service in ASP.NET application.
I can write the following code to detect preferred client culture:
CultureInfo culture = null;
if (Request.UserLanguages!=null && Request.UserLanguages.Length>0) {
string lang = Request.UserLanguages[0];
if (!String.IsNullOrEmpty(lang)) {
try {
culture = new CultureInfo(lang) ;
}
catch {}
}
}
And use this expression to get string from resources:
WebResources.ResourceManager.GetString(stringName, culture);
But I want to use something similar to Page directive attributes:
Culture="Auto" UICulture="Auto"
Is it possible?
Firstly, this all depends on the client transmitting the headers from which the UserLanguages collection gleans it's information. Most consumers of your service if they're not browsers will not transmit that information.
Secondly, no I don't believe it is possible to do it automatically, however you could write something into the HttpContext.Items collection for the values and then wrap up
public string GetResource(string Key)
{
culture = HttpContext.Items["UserLanguage"];
WebResources.ResourceManager.GetString(stringName, culture);
}
Then your code would just read: -
GetResource("Blah");
Thanks,
Phil.