how to generate a Http Request for AAD? - http

so, I get the Access Token and I want to create a request...
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", accesToken);
HttpResponseMessage response = await httpClient.GetAsync("https://graph.microsoft.com/v1.0/users");
Also, the Problem may be on setting the scopes for the authentication...i set it to:
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
But I don't know if it gets all application permissions that I have (it is a deamon).

You can use this sample which will help you to create events with same client credential flow which you are using but you need to change some things here.
You need to first give the Calendar.ReadWrite permission in the Azure portal for your app.
You need to add the below code in the Program.cs
if (result != null)
{
var httpClient = new HttpClient();
var apiCaller = new ProtectedApiCallHelper(httpClient);
await apiCaller.CallWebAPIToPostEvent($"{config.ApiUrl}v1.0/users/{user obj id}/calendars/{calendar id}/events", result.AccessToken, Display);
}
Then you need to add the below classes in the protectedApiCallHelper.cs
public class Event
{
[JsonProperty("subject")]
public string Subject { get; set; }
[JsonProperty("body")]
public Body Body;
[JsonProperty("start")]
public TimeAndDate Start;
[JsonProperty("end")]
public TimeAndDate End;
[JsonProperty("location")]
public Location Location;
[JsonProperty("attendees")]
public List<Attendees> Attendees;
}
public class Body
{
[JsonProperty("contentType")]
public string ContentType { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
}
public class TimeAndDate
{
[JsonProperty("dateTime")]
public string DateTime { get; set; }
[JsonProperty("timeZone")]
public string TimeZone { get; set; }
}
public class Location
{
[JsonProperty("displayName")]
public string DisplayName { get; set; }
}
public class Attendees
{
[JsonProperty("emailAddress")]
public EmailAddress EmailAddress;
[JsonProperty("type")]
public string Type;
}
public class EmailAddress
{
[JsonProperty("address")]
public string Address { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
In this same ProtectedApiCallHelper class you can create a post request and get the details by adding the below code
public async Task CallWebAPIToPostEvent(string webApiUrl, string accessToken, Action<JObject> processResult)
{
var defaultRequetHeaders = HttpClient.DefaultRequestHeaders;
if (defaultRequetHeaders.Accept == null || !defaultRequetHeaders.Accept.Any(m => m.MediaType == "application/json"))
{
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
defaultRequetHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
var payload = new Event
{
Subject = "Let's go for lunch",
Body = new Body
{
ContentType = "HTML",
Content = "Does mid month work for you?"
},
Start = new TimeAndDate
{
DateTime = "2019-03-15T12:00:00",
TimeZone = "Pacific Standard Time"
},
End = new TimeAndDate
{
DateTime = "2019-03-15T14:00:00",
TimeZone = "Pacific Standard Time"
},
Location = new Location
{
DisplayName = "Harry's Bar"
},
Attendees = new List<Attendees>
{
new Attendees
{
EmailAddress = new EmailAddress
{
Address = "Shiva#nishantsingh.live",
Name = "Shiva"
},
Type = "required"
}
}
};
// Serialize our concrete class into a JSON String
var stringPayload = await Task.Run(() => JsonConvert.SerializeObject(payload));
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await HttpClient.PostAsync(webApiUrl, httpContent);
if (response.Content != null)
{
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
}
This will help you create the event with these details.

Related

Object is null after JsonConvert.DeserializeObject

I have looked at some forum posts and found no solution to my problem, so now I ask you for help. First i show you what the result of my HttpGet is and then i show you the not working deserialization.
Working example: I use the same code for an HttpGet to get a json result.
[HttpGet]
[Route("~/get_new_authtoken")]
public async Task<IActionResult> GetNewAuthTokenAsync()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://testApi/WebService/");
string APIConnection = _configuration.GetValue<string>("APIConnection");
HttpResponseMessage response = client.PostAsync("authtoken", new StringContent(string.Format(APIConnection))).Result;
if (response.IsSuccessStatusCode)
{
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
return Ok(ex.Message);
}
}
with following result when i call it via Postman
Not working deserialization: I store the token in a database and want to update it when it expires.
Object i want to desiralize in:
public class AuthToken
{
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
[JsonPropertyName("token_type")] public string TokenType { get; set; }
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
}
when i add the following code to the httpget above to test the deserializationthe object Authtoken is always null.
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
Like this->
if (response.IsSuccessStatusCode)
{
//To test
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
//To test
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
Updated the testint to following code:
AuthToken newAccessToken = new AuthToken();
var responseString = await response.Content.ReadAsStringAsync();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(responseString);
result of the responseString:
JsonPropertyNameAttribute is from System.Text.Json while JsonConvert.DeserializeObject is part of Newtonsoft.Json either switch to former completely by using System.Text.Json.JsonSerializer.Deserialize:
AuthToken newAccessToken = JsonSerializer.Deserialize<AuthToken>(...);
// or just use ReadFromJsonAsync instead of ReadAsStringAsync
Or use attributes for latter:
public class AuthToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
// ...
}

Xamarin Essentials WebAuthenticator.AuthenticateAsync method doesn't return any result

I have added a WebAuthenticator.AuthenticateAsync method in my xamarin forms app with start up Url as "https://accounts.google.com/o/oauth2/auth"
and call back url as "myapp://"
I have also tried with call back url as "com.googleusercontent.apps.{clientId}:/oauth2redirect"
I am doing this to add google login in my xamarin forms app.
On this browser with available google accounts are been showing up and after successful completion of email authentication it returns to app but result is not returned from WebAuthenticator.AuthenticateAsync method.
On second time invocation of this method returns the first invocation result as cancelled by user and the browser opens again for second time email authentication.
But it works in ios.
I have added 3 classes
public class Auth0Client
{
private readonly OidcClient oidcClient;
public Auth0Client(Auth0ClientOptions options)
{
var discovery = new DiscoveryPolicy
{
ValidateEndpoints = false,
Authority = "https://accounts.google.com"
};
oidcClient = new OidcClient(new OidcClientOptions
{
Authority = $"https://accounts.google.com/o/oauth2/auth",
ClientId = options.ClientId,
Scope = options.Scope,
RedirectUri = options.RedirectUri,
Browser = options.Browser,
ProviderInformation = options.ProviderInformation,
Policy = new Policy
{
Discovery = discovery,
RequireAccessTokenHash = false
},
});
}
public IdentityModel.OidcClient.Browser.IBrowser Browser
{
get
{
return oidcClient.Options.Browser;
}
set
{
oidcClient.Options.Browser = value;
}
}
public async Task<LoginResult> LoginAsync()
{
return await oidcClient.LoginAsync();
}
}
public class Auth0ClientOptions
{
public Auth0ClientOptions()
{
}
public string Domain { get; set; }
public string ClientId { get; set; }
public string RedirectUri { get; set; }
public string Scope { get; set; }
public IBrowser Browser { get; set; }
public ProviderInformation ProviderInformation { get; set; }
}
public class WebBrowserAuthenticator : IBrowser
{
public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default)
{
try
{
WebAuthenticatorResult result = await WebAuthenticator.AuthenticateAsync(
new Uri(options.StartUrl),new Uri(options.EndUrl));
var url = new RequestUrl(options.EndUrl)
.Create(new Parameters(result.Properties));
return new BrowserResult
{
Response = url,
ResultType = BrowserResultType.Success
};
}
catch (Exception ex)
{
return new BrowserResult
{
ResultType = BrowserResultType.UserCancel,
ErrorDescription = "Login canceled by the user."
};
}
}
}
In view model we are creating authoclient
private async void NavigateToGoogleLogin(object obj)
{
string clientId = null;
string redirectUri = null;
switch (Device.RuntimePlatform)
{
case Device.iOS:
clientId = AppConstants.GoogleiOSClientId;
redirectUri = AppConstants.GoogleiOSRedirectUrl;
break;
case Device.Android:
clientId = AppConstants.GoogleAndroidClientId;
redirectUri = AppConstants.GoogleAndroidRedirectUrl;
break;
}
var auth0client = new Auth0Client(new Auth0ClientOptions()
{
Domain = "accounts.google.com/o/oauth2/auth",
ClientId = clientId,
RedirectUri = redirectUri,
Scope = AppConstants.GoogleScope,
Browser = new WebBrowserAuthenticator(),
ProviderInformation = new ProviderInformation
{
IssuerName = "accounts.google.com",
AuthorizeEndpoint = AppConstants.GoogleAuthorizeUrl,
TokenEndpoint = AppConstants.GoogleAccessTokenUrl,
UserInfoEndpoint = AppConstants.GoogleUserInfoUrl,
KeySet = new JsonWebKeySet(),
},
});
var loginResult = await auth0client.LoginAsync();
}
We are using below constants in authoclient object creation
internal static string GoogleScope = "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile";
internal static string GoogleAuthorizeUrl = "https://accounts.google.com/o/oauth2/auth";
internal static string GoogleAccessTokenUrl = "https://www.googleapis.com/oauth2/v4/token";
internal static string GoogleUserInfoUrl = "https://www.googleapis.com/oauth2/v3/userinfo";
Xamarin forms version:5.0.0.2012
Xamarin essentials: 1.7.3
Thanks in advance

Consuming web api with RestSharp basic authentication return null

I am trying to consume an endpoint with RestSharp with Basic authentication.
I followed the instructions on the documentation https://restsharp.dev/getting-started/getting-started.html
The request was successful but I think the request body was malformed.
How can I get this to work
internal BalanceInquiryResponse BalanceInquiryRest(BalanceInquiryRequest BalanceInquiryRequest, Settings Settings)
{
// BalanceInquiryResponse BalanceInquiryResponse = new BalanceInquiryResponse();
var client = new RestClient(Settings.BaseUrl + "All/Inquiry");
client.Authenticator = new HttpBasicAuthenticator(Settings.Username, Settings.Password);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(new
{
Acc = BalanceInquiryRequest.Acc
});
IRestResponse response = client.Execute(request);
IRestResponse<BalanceInquiryResponse> res = client.Execute<BalanceInquiryResponse>(request);
if (response.IsSuccessful)
{
BalanceInquiryResponse = new BalanceInquiryResponse
{
responseInquiry = res.Data.responseInquiry,
ResponseDescription = res.Data.ResponseDescription,
ResponseMessage = res.Data.ResponseMessage
};
return BalanceInquiryResponse;
}
else
{
BalanceInquiryResponse = new BalanceInquiryResponse
{
ResponseDescription = responseses.ErrorMessage,
};
return BalanceInquiryResponse;
}
}
This is my response body
{
"responseMessage": "Successful",
"responseDescription": "Request Successful",
"responseInquiry": null
}
When I tried with postman I got
{
"ResponseMessage": "Successful",
"ResponseDescription": "Request Successful",
"response": {
"AvalBal": 586324.42,
"ReverAmt": 0,
"AccCurrency": "US "
}
}
IRestResponse<BalanceInquiryResponse> res = client.Execute<BalanceInquiryResponse>(request);
So there is a specific reason...you are putting BalanceInquiryResponse in the generic IRestResponse above.
With the above call, this should automatically hydrate the BalanceInquiryResponse object, and you shouldn't need to hand map.
Aka, you should ~not~ need this below code:
BalanceInquiryResponse = new BalanceInquiryResponse
{
responseInquiry = res.Data.responseInquiry,
ResponseDescription = res.Data.ResponseDescription,
ResponseMessage = res.Data.ResponseMessage
};
I think your issue is that your POCO object (BalanceInquiryResponse) should perfectly match the "structure" of the JSON.
Change your BalanceInquiryResponse to PERFECTLY match the json "properties".
and recognize you have a nested object.
I think it it would be:
public class ResponsePoco {
public double AvalBal { get; set; }
public int ReverAmt { get; set; }
public string AccCurrency { get; set; }
}
public class BalanceInquiryResponse{
public string ResponseMessage { get; set; }
public string ResponseDescription { get; set; }
public ResponsePoco response { get; set; }
}
Pay attention the to "ResponsePoco response"..note the variable name is LOWERCASE .. because...the json has a lowercase "response" in it.
I have called the (child) object "ResponsePoco" to highlight the difference between the object name and the variable name.
If you cannot "perfectly" match the Poco properties. you can use attributes to "massage" the discrepencies. As seen here:
https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm
public class Videogame
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("release_date")]
public DateTime ReleaseDate { get; set; }
}

Integration Testing Forms with Nested Objects

I am using .NET Core with Boilerplate. I'm trying to unit test some new forms that require that I have nested objects with properties. The Integration Tests use AbpAspNetCoreIntegratedTestBase<Startup> which uses an instance of both HttpClient and TestServer. The client has various types of methods at its disposal. There are GetAsync, PostAsync, SendSync and PutAsync methods just to name a few.
I thought I had gotten comfortable with some of the methods and helper methods in this frame work and have been successful thus far. However, I have a form with an Model called Vendor, the Vendor has an Address Model as part of the view model. This is so I can reuse the Address View Model with other items in the application that also require Address(es).
One of the helpers that is used with BoilerPlate is GetUrl<TController>(string actionName, object queryStringParamsAsAnonymousObject) Since this is a Post from a form I'm attempting to use public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) No matter what I'm attempting to do, I'm getting a 400 Bad Request response and my test fails before it even gets inside the controller method. I'm at a loss of how to handle this.
Here are my Models:
VendorViewModel:
[AutoMap(typeof(Domains.Vendor))]
public class VendorViewModel : BaseViewModelEntity
{
[Required]
public string Name { get; set; }
[Required]
public string PointOfContact { get; set; }
[Required]
public string Email { get; set; }
[Required]
public int AddressId { get; set; }
//[Required]
//public string Address1 { get; set; }
//public string Address2 { get; set; }
//public string Address3 { get; set; }
//[Required]
//public string City { get; set; }
//[Required]
//public int State { get; set; }
//[Required]
//public string Zip { get; set; }
//[Required]
//public string Phone { get; set; }
//public string Fax { get; set; }
public AddressViewModel VendorAddress { get; set; }
public VendorViewModel()
{
VendorAddress = new AddressViewModel();
}
public VendorViewModel(VendorDto vendor)
{
Id = vendor.Id;
Name = vendor.Name;
IsActive = vendor.IsActive;
PointOfContact = vendor.PointOfContact;
Email = vendor.Email;
AddressId = vendor.AddressId;
CreatorUserId = vendor.CreatorUserId;
CreationTime = vendor.CreationTime;
DeleterUserId = vendor.DeleterUserId;
DeletionTime = vendor.DeletionTime;
LastModificationTime = vendor.LastModificationTime;
LastModifierUserId = vendor.LastModifierUserId;
//Address1 = vendor.Address.Address1;
//Address2 = vendor.Address.Address2;
//Address3 = vendor.Address.Address3;
//City = vendor.Address.City;
//State = vendor.Address.State;
//Zip = vendor.Address.Zip;
//Phone = vendor.Address.Phone;
//Fax = municipalities.Address.Fax;
VendorAddress = new AddressViewModel()
{
Id = vendor.Address.Id,
Address1 = vendor.Address.Address1,
Address2 = vendor.Address.Address2,
Address3 = vendor.Address.Address3,
City = vendor.Address.City,
State = vendor.Address.State,
Zip = vendor.Address.Zip,
Phone = vendor.Address.Phone,
Fax = vendor.Address.Fax,
CreationTime = vendor.Address.CreationTime,
};
}
}
Address View Model:
public class AddressViewModel : BaseViewModelEntity
{
[Required]
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
[Required]
public string City { get; set; }
[Required]
public int State { get; set; }
[Required]
public string Zip { get; set; }
[Required]
public string Phone { get; set; }
public string Fax { get; set; }
public AddressViewModel()
{
}
public AddressViewModel(AddressDto address)
{
Id = address.Id;
Address1 = address.Address1;
Address2 = address.Address2;
Address3 = address.Address3;
City = address.City;
State = address.State;
Zip = address.Zip;
Phone = address.Phone;
Fax = address.Phone;
CreatorUserId = address.CreatorUserId;
CreationTime = address.CreationTime;
DeleterUserId = address.DeleterUserId;
DeletionTime = address.DeletionTime;
LastModificationTime = address.LastModificationTime;
LastModifierUserId = address.LastModifierUserId;
}
}
I have my Test set up with xUnit
//Arrange
//Add Client Headers so User Auth and Permission Checkers work correctly
Client.DefaultRequestHeaders.Add("my-name", "admin");
Client.DefaultRequestHeaders.Add("my-id", "2");
//set up test data
var addressViewModel = new AddressViewModel()
{
Address1 = "123 This Way", City = "Arlington", State = 44, Zip = "76001", Phone = "8175555555",
CreationTime = DateTime.Now
};
var viewModelSave = new VenderViewModel()
{
Name = "Controller Test Name",
PointOfContact = "Tom Jerry",
Email = "Tom.Jerry#yolo.com",
CreationTime = DateTime.Now,
LastModificationTime = null,
IsActive = true,
AddressId = 0,
VendorAddress = addressViewModel
//Address1 = "123 This Way",
//City = "Arlington",
//State = 44,
//Zip = "76001",
//Phone = "8175555555"
};
/* This is an attempt to use string interpolation to create querystring parameters */
//var rawData =
// $"?Name={viewModelSave.Name}&Id={viewModelSave.Id}&PointOfContat=${viewModelSave.PointOfContact}&Email={viewModelSave.Email}&CreationTime={DateTime.Now}" +
// $"&LastModificationTime=&IsActive={viewModelSave.IsActive}&AddressId={viewModelSave.AddressId}&VendorAddress.Id={viewModelSave.VendorAddress.Id}&VendorAddress.Address1={viewModelSave.VendorAddress.Address1}" +
// $"&VendorAddress.City={viewModelSave.VendorAddress.City}&VendorAddress.State={viewModelSave.VendorAddress.State}&VendorAddress.Zip={viewModelSave.VendorAddress.Zip}&VendorAddress.Phone={viewModelSave.VendorAddress.Phone}" +
// $"&VendorAddress.CreationTime={DateTime.Now}&VendorAddress.IsActive={viewModelSave.VendorAddress.IsActive}";
/*This is an attempt to create a json object that could be serialize into an object as the "queryStringParamsAsAnonymousObject" that can be used in the GetUrl Helper method below */
var rawData = $"{{'Name':'Controller Test Name','PointOfContact':'Tom Jerry', 'Email': 'Tom.Jerry#yolo.com',"
+ "'CreationTime':'" + DateTime.Now + "','LastModificationTime':'','IsActive' : 'true','AddressId':'0','Address.Address1':'123 This Way',"
+ "'Address.City':'Arlington','Address.State':'44','Address.Zip':'76001','Address.Phone':'8175555556','Address.IsActive':'true'}";
var jsonData = JsonConvert.DeserializeObject(rawData);
//Serialize ViewModel to send with Post as part of the HttpContent object
var data = JsonConvert.SerializeObject(viewModelSave);
var vendorAddress = new
{
viewModelSave.vendorAddress.Id,
viewModelSave.vendorAddress.Address1,
viewModelSave.vendorAddress.City,
viewModelSave.vendorAddress.State,
viewModelSave.vendorAddress.Zip,
viewModelSave.vendorAddress.Phone,
viewModelSave.vendorAddress.IsActive,
viewModelSave.vendorAddress.CreationTime
};
//actually get the url from helper method (with various attempts at creating an anonymousObject directly
var url = GetUrl<VendorController>(nameof(VendorController.SaveVendor),
new
{
viewModelSave.Id,
viewModelSave.Name,
viewModelSave.PointOfContact,
viewModelSave.Email,
viewModelSave.CreationTime,
viewModelSave.LastModificationTime,
viewModelSave.IsActive,
viewModelSave.AddressId,
vendorAddress
//VendorAddress_Address1 = vendorAddress.Address1,
//VendorAddress_Id = vendorAddress.Id,
//VendorAddress_City = vendorAddress.City,
//VendorAddress_State = vendorAddress.State,
//VendorAddress_Zip = vendorAddress.Zip,
//VendorAddress_Phone = vendorAddress.Phone,
//VendorAddress_IsActive = vendorAddress.IsActive,
//VendorAddress = new
//{
// viewModelSave.VendorAddress.Id,
// viewModelSave.VendorAddress.Address1,
// viewModelSave.VendorAddress.City,
// viewModelSave.VendorAddress.State,
// viewModelSave.VendorAddress.Zip,
// viewModelSave.VendorAddress.Phone,
// viewModelSave.VendorAddress.IsActive,
// viewModelSave.VendorAddress.CreationTime
//},
//viewModelSave.Address1,
//viewModelSave.City,
//viewModelSave.State,
//viewModelSave.Zip,
//viewModelSave.Phone
}
);
var content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
var message = new HttpRequestMessage {
Content = content,
Method = HttpMethod.Post,
RequestUri = new Uri("http://localHost" + url)
};
//Act
var response = await PostResponseAsObjectAsync<AjaxResponse>(url, content);
//Assert
var count = UsingDbContext(context => { return context.Municipalities.Count(x => x.IsActive); });
response.ShouldBeOfType<AjaxResponse>();
response.Result.ShouldNotBeNull();
count.ShouldBe(3);
}
As I attempt to debug what is happening. I've noticed that the VendorAddress properties that are sent via the test request do not match what the actual form post looks like when parsed in Chrome developer tools. In Chrome I see (example:
PointOfContact:"Tom Jerry"
IsActive:True
VendorAddress.Address1:"123 This Way"
VendorAddress.City: "Arlington")
I cannot get my test data into that same format, therefore its not binding correctly to my view models on post, and thus returns a 400 response and fails the test.
I have gotten it to work if I remove the Address View Model all together and put those properties as properties of the VendorViewModel. However, I would run into the same if not similar issue if I'm attempting to save a collection of objects along with the main view model.
I feel like there has to be a way to submit test form data via integration tests with boilerplate. I just need some missing piece to this puzzle.
The Solution that is working for both Post and Send Requests:
.NET Core has a QueryHelper class that will take a dictionary and a uri string and convert it into a url with querystring parameters. QueryHelpers.AddQueryString(string uri, IDictionary queryString) This is part of Microsoft.AspNetCore.WebUtilities.
Using this method I was able to properly prepare my formData. For a Post Request the Test would look like this
//Arrange
//Add Client Headers so User Auth and Permission Checkers work correctly
Client.DefaultRequestHeaders.Add("my-name", "admin");
Client.DefaultRequestHeaders.Add("my-id", "2");
//set up test data
var rawData = new Dictionary<string, string>(){{ "Id", "0"}, {"Name", "Controller Test Name"}, {"PointOfContact", "Tom Jerry"}
, {"Email", "Tom.Jerry#yolo.comy"}, {"CreationTime", $"{DateTime.Now}"}, {"LastModificationTime", ""}, {"IsActive", "true"}, {"AddressId", "0"}
, {"VendorAddress.Id", "0"}, {"VendorAddress.Address1", "123 This Way"}, {"VendorAddress.City", "Arlington"}, {"VendorAddress.State", "44"}, {"VendorAddress.Zip", "76001"}
, {"VendorAddress.Phone", "8175555555"}, {"VendorAddress.Fax", ""}, {"VendorAddress.IsActive", "true"}, {"VendorAddress.CreationTime", $"{DateTime.Now}"}, {"VendorAddress.LastModificationTime", ""}
};
var jsonData = JsonConvert.DeserializeObject(rawData);
//Serialize ViewModel to send with Post as part of the HttpContent object
var data = JsonConvert.SerializeObject(viewModelSave);
//actually get the url from helper method
var url = GetUrl<VendorController>(nameof(VendorController.SaveVendor));
var content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
//Act
var response = await PostResponseAsObjectAsync<AjaxResponse>(url, content);
//Assert
var count = UsingDbContext(context => { return context.Municipalities.Count(x => x.IsActive); });
response.ShouldBeOfType<AjaxResponse>();
response.Result.ShouldNotBeNull();
count.ShouldBe(3);
Send Request Test would look like this
//Arrange
//Add Client Headers so User Auth and Permission Checkers work correctly
Client.DefaultRequestHeaders.Add("my-name", "admin");
Client.DefaultRequestHeaders.Add("my-id", "2");
//set up test data
var rawData = new Dictionary<string, string>(){{ "Id", "0"}, {"Name", "Controller Test Name"}, {"PointOfContact", "Tom Jerry"}
, {"Email", "Tom.Jerry#yolo.comy"}, {"CreationTime", $"{DateTime.Now}"}, {"LastModificationTime", ""}, {"IsActive", "true"}, {"AddressId", "0"}
, {"VendorAddress.Id", "0"}, {"VendorAddress.Address1", "123 This Way"}, {"VendorAddress.City", "Arlington"}, {"VendorAddress.State", "44"}, {"VendorAddress.Zip", "76001"}
, {"VendorAddress.Phone", "8175555555"}, {"VendorAddress.Fax", ""}, {"VendorAddress.IsActive", "true"}, {"VendorAddress.CreationTime", $"{DateTime.Now}"}, {"VendorAddress.LastModificationTime", ""}
};
var jsonData = JsonConvert.DeserializeObject(rawData);
//Serialize ViewModel to send with Post as part of the HttpContent object
var data = JsonConvert.SerializeObject(viewModelSave);
//actually get the url from helper method
var url = GetUrl<VendorController>(nameof(VendorController.SaveVendor));
var content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
var message = new HttpRequestMessage {
Content = content,
Method = HttpMethod.Post,
RequestUri = new Uri("http://localHost" + url)
};
//Act
var response = await SendResponseAsObjectAsync<AjaxResponse>(message);
//Assert
var count = UsingDbContext(context => { return context.Municipalities.Count(x => x.IsActive); });
response.ShouldBeOfType<AjaxResponse>();
response.Result.ShouldNotBeNull();
count.ShouldBe(3);

XML File Model Mapping asp.net MVC3 ( Dynamically Map an xml file to a model class asp.net mvc3 )

I am trying to implement a payment gateway(INTUIT payment gateway). I would like to serialize an xml to an model class and save into my database. I am using Desktop Model for intuit payment gateway, as the hosted model is a pain to get working with especially ssl certificates, so i dont want to try that.
I must mention i am able to get the response using the below mentioned code, where i am stuck at the moment is serialize the xml and save the response into the database. This xml is pulled from a folder in my xmlfiles folder located in my project.
For sample xml format, check out this one. https://ipp.developer.intuit.com/0085_QuickBooks_Windows_SDK/qbms/0060_Documentation/Sending_Requests
this is an xml file i am trying to post to url (https://merchantaccount.ptc.quickbooks.com/j/AppGateway)
<?xml version="1.0"?>
<?qbmsxml version="4.5"?>
<QBMSXML>
<SignonMsgsRq>
<SignonDesktopRq>
<ClientDateTime>2012-07-25T17:13:45</ClientDateTime>
<ApplicationLogin>abc.abc.us</ApplicationLogin>
<ConnectionTicket>TGT-1-g42FGaMfOTQ82GcWFBpsuQ</ConnectionTicket>
</SignonDesktopRq>
</SignonMsgsRq>
<QBMSXMLMsgsRq>
<CustomerCreditCardChargeRq>
<TransRequestID>4540453787200</TransRequestID>
<CreditCardNumber>4111111111111111</CreditCardNumber>
<ExpirationMonth>12</ExpirationMonth>
<ExpirationYear>2016</ExpirationYear>
<IsCardPresent>false</IsCardPresent>
<Amount>10.00</Amount>
</CustomerCreditCardChargeRq>
</QBMSXMLMsgsRq>
</QBMSXML>
The Controller i use to make a post to the url
public ActionResult Index()
{
WebRequest req = null;
WebResponse rsp = null;
string fileName = Server.MapPath("~/XMLData/XMLFile1.xml");
string uri = "https://merchantaccount.ptc.quickbooks.com/j/AppGateway";
req = WebRequest.Create(uri);
//req.Proxy = WebProxy.GetDefaultProxy(); // Enable if using proxy
req.Method = "POST"; // Post method
req.ContentType = "application/x-qbmsxml"; // content type
// Wrap the request stream with a text-based writer
StreamWriter writer = new StreamWriter(req.GetRequestStream());
// Write the XML text into the stream
writer.WriteLine(this.GetTextFromXMLFile(fileName));
writer.Close();
// Send the data to the webserver
rsp = req.GetResponse();
// var resp = (Object)rsp.GetResponseStream();
if (rsp != null)
{
StreamReader inStream = new StreamReader(rsp.GetResponseStream());
var data = inStream.ReadToEnd();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(data);
string path = Server.MapPath("~/XMLData/SampleXmlE2E.xml");
xmlDoc.Save(path);//regenerates the xml file in different system.
}
return View();
//XElement root = new XElement("root");
//root.Add(new XElement("element1"));
//root.Add(new XElement("element2"));
//root.Add(new XAttribute("attribute1", "a value"));
//return new XmlResult(root);
}
private string GetTextFromXMLFile(string file)
{
StreamReader reader = new StreamReader(file);
string ret = reader.ReadToEnd();
reader.Close();
return ret;
}
private string SendRequest(Uri UriObj, string data)
{
string _result;
var request = (HttpWebRequest)WebRequest.Create(UriObj);
request.Method = "POST";
request.ContentType = "text/xml";
var writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
var response = (HttpWebResponse)request.GetResponse();
var streamResponse = response.GetResponseStream();
var streamRead = new StreamReader(streamResponse);
_result = streamRead.ReadToEnd().Trim();
streamRead.Close();
streamResponse.Close();
response.Close();
return _result;
}
Any help would be appreciated. Thanks
Varun,
[Edit -update]
Based on this XML:
<?qbmsxml version="4.5"?>
<QBMSXML>
<SignonMsgsRq>
<SignonDesktopRq>
<ClientDateTime>2012-07-25T17:13:45</ClientDateTime>
<ApplicationLogin>app.app.login.url</ApplicationLogin>
<ConnectionTicket>TGT-1-g42FGaMfOTQ82GcWFBpsuQ</ConnectionTicket>
</SignonDesktopRq>
</SignonMsgsRq>
<QBMSXMLMsgsRq>
<CustomerCreditCardChargeRq>
<TransRequestID>4540453787200</TransRequestID>
<CreditCardNumber>4111111111111111</CreditCardNumber>
<ExpirationMonth>12</ExpirationMonth>
<ExpirationYear>2016</ExpirationYear>
<IsCardPresent>false</IsCardPresent>
<Amount>10.00</Amount>
</CustomerCreditCardChargeRq>
</QBMSXMLMsgsRq>
</QBMSXML>
Here's the class structure that you'd need to deserialize into as per the example above:
[XmlRoot("QBMSXML")]
public class QbmsXml
{
[XmlElement("SignonMsgsRq")]
public SignonMsgsRq SignonMsgsRq { get; set; }
[XmlElement("QBMSXMLMsgsRq")]
public QbmsXmlMsgsRq QbmsXmlMsgsRq { get; set; }
}
public class SignonMsgsRq
{
[XmlElement("SignonDesktopRq")]
public SignonDesktopRq SignonDesktopRq { get; set; }
}
public class SignonDesktopRq
{
[XmlElement("ClientDateTime")]
public DateTime ClientDateTime { get; set; }
[XmlElement("ApplicationLogin")]
public string ApplicationLogin { get; set; }
[XmlElement("ConnectionTicket")]
public string ConnectionTicket { get; set; }
}
public class QbmsXmlMsgsRq
{
[XmlElement("CustomerCreditCardChargeRq")]
public CustomerCreditCardChargeRq CustomerCreditCardChargeRq { get; set; }
}
public class CustomerCreditCardChargeRq
{
[XmlElement("TransRequestID")]
public Int64 TransRequestID { get; set; }
[XmlElement("CreditCardNumber")]
public string CreditCardNumber { get; set; }
[XmlElement("ExpirationMonth")]
public int ExpirationMonth { get; set; }
[XmlElement("ExpirationYear")]
public int ExpirationYear { get; set; }
[XmlElement("IsCardPresent")]
public bool IsCardPresent { get; set; }
[XmlElement("Amount")]
public double Amount { get; set; }
}
Just use the xmlSerialiser along the lines of:
class Program
{
private static T DeSerialize<T>(string fromXmlFile) where T: class
{
if (!File.Exists(fromXmlFile))
{
return default(T);
}
T deserializedClass;
var serializer = new XmlSerializer(typeof(T));
// ToDo: add error catching etc
using (var reader = new StreamReader(fromXmlFile))
{
deserializedClass = (T)serializer.Deserialize(reader);
}
return deserializedClass;
}
static void Main(string[] args)
{
var yourXmlFilePath = #"d:\temp\xmltest.xml";
var deserializedClass = DeSerialize<QbmsXml>(yourXmlFilePath);
Console.WriteLine(deserializedClass
.QbmsXmlMsgsRq
.CustomerCreditCardChargeRq.Amount);
Console.Read();
}
}
hope this helps.

Resources