I have a C# backend code that receives a POST request from the client side code in TypeScript.
The JSON is done for the POST with JSON.stringify(objectOfData);
In the C# code I am getting an exception when I try to use the object like so:
// Passed into this function is InboundObjectDTO inboundObject
// inboundObject.Email in debugger is like so: "\"a#example.com\""
var message = new MailMessageDTO
{
Subject = "My Subject",
MailAddresses = new List<MailAddress>()
};
message.MailAddresses.Add(new MailAddress(inboundObject.Email));
Am I supposed to deserialize the object somehow before hand? I have 3 strings in the object: email, message, and name.
The last line of code above gives me "An invalid character in MailAddresses exception." I am guessing it needs to have all the extra quotes and such removed in a proper way.
As OP had originally postulated, the issue is the quotes around the email address, all we need to do is remove those quotes. This process is referred to as Sanitizing the input.
The original methodology was hard to follow and the exception information posted was ambiguous, this solution shows how to sanitise the input and return more relevant information with the exception.
The example you have pasted ""a#example.com"" would not fail in your original code that included the santize logic, if you had simply used the result of the sanitize step!
You should wrap the code block in a try-catch so you can capture the exception and output the specific string value that has failed:
string email = inboundObject.Email;
MailMessageDTO message = null;
try
{
// sanitized the email, removed known invalid characters
email = email.Replace("\"", "");
// construct the payload object
message = new MailMessageDTO
{
Subject = "My Subject",
MailAddresses = new List<MailAddress>()
};
message.MailAddresses.Add(new MailAddress(email));
}
catch (Exception ex)
{
throw new ApplicationException($"Failed to construct MailMessage for email: {email}", ex);
}
Now when this fails, we have more information to work with inside the exception, infact this situation itself probably warrants it's own separate reusable method:
public MailAddress SanitizeEmail(string emailAddress)
{
string email = emailAddress;
try
{
// sanitized the email, removed known invalid characters
email = email.Replace("\"", "");
// TODO: add other rules an replacement cases as you find them
return new MailAddress(email);
}
catch (Exception ex)
{
throw new ApplicationException($"Failed to sanitize email address: '{email}' [original input: '{emailAddress ?? "NULL" }']", ex);
}
}
You could call this using:
message.MailAddresses.Add(SanitizeEmail(email));
Update
OP's original code included references and test conditions that are no longer in the posted code, this response has only been marginally updated to reflect those changes
If you are posting json data to controller action,you can use [FromBody],[FromBody] will get values from the request body:
public IActionResult Index([FromBody]inboundObject inboundObject)
{
...
}
Or you can use JsonConvert.DeserializeObject to deserialize the the JSON to specified .NET type:
message.MailAddresses.Add(new MailAddress(JsonConvert.DeserializeObject<string>(inboundObject.Email)));
Related
I'm creating an application which talks to an external API, the external API only accepts XML posts for dealing with information. I've written most of it and I'm at a point where I need to feed the XML information which includes the DTD to the API and I cannot get it to work.
CarApiService
This is where I'm struggling, I have the required XML which I need to post and so I thought I would used the XmlDocument to load it, then, rather than using PostAsync I could use PostAsXmlAsync which is more appropriate.
public async Task<string> RequestParts(string partNumber = "0")
{
//Store any errors as a string
string errors;
//LoadXML
XmlDocument document = new();
document.LoadXml("<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE gmPartsRequest PUBLIC '-//GeneralMotors//DTD GmPartsRequest v1//EN' 'http://dtd.generalmotors.com/parts_request_version1.dtd'>" +
"<partsService version='1.4' dealershipId='xxx'></partsService>");
//Create HttpClient
var client = _clientFactory.CreateClient("external");
try
{
var postData = await client.PostAsXmlAsync(client.BaseAddress, document);
errors = null;
return something.ToString();
}
catch (Exception ex)
{
errorString = $"There was an error getting your parts data: { ex.Message }";
return errors;
}
}
There are a few things that bother me about my above code and I'm hoping someone can help:
PostAsXmlAsync returns an error when it executes and I'm not sure how to resolve it:
There was an error getting your parts data: Type
'System.Xml.XmlElement' with data contract name
'XmlElement:http://schemas.datacontract.org/2004/07/System.Xml' is not
expected. Add any types not known statically to the list of known
types - for example, by using the KnownTypeAttribute attribute or by
adding them to the list of known types passed to
DataContractSerializer.
Given that I store the API information in the startup file, is there any way to avoid having to supply the PostAsXmlAsync with the base address in this way?
Should this really be returning as a string given that I'm supposed to be posting and receiving XML?
I built a login/register system, and I want that when you create a username it checks if email exists, it works fine and it shows the message box "Email exists", but when it is a new user and there is no email that exists, it crashes.
Here is the exception message:
(System.NullReferenceException) Message=The object reference was not set to an object instance
Code:
FirebaseResponse response = await client.GetTaskAsync("Information/" + Emailtextbox.TextName);
Data result = response.ResultAs<Data>();
if (Emailtextbox.TextName == result.Email)
{
MessageBox.Show("Email exists");
} else
{
var data = new Data
{
Email = Emailtextbox.TextName,
Fullname = Fullnametextbox.TextName,
Password = EncryptSHA.GetShaData(PasswordTextbox.TextName)
}
};
Updating this based on the screenshot of the error as well as the information provided in the following comments.
It looks like your error has to do with what's being returned from your client.GetTaskAsync("Information/" + Emailtextbox.Textname); call.
My recommendation would be to try and understand what it is you're receiving from that call (what's stored in your response object). With the latest screenshot I see that the Body is null, and that might be part of the problem. Try expanding what you see in the Response object in your response and see if you're even receiving any kind of data you can use and go from there.
I need all the text in the body for incoming email.
I tried:
var mesage = GetMessage(service, "me", 1);
Console.WriteLine(mesage.Snippet);
public static Message GetMessage(GmailService service, String userId, String messageId)
{
try
{
return service.Users.Messages.Get(userId, messageId).Execute();
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
return null;
}
But I am getting just snippet as shown in the screenshot.
Incoming mail to me:
Result:
Looking at the documentation, Message.Snippet only returns a short part of the message text. You should instead use Message.Raw, or more appropriately, Message.Payload.Body?
var message = GetMessage(service, "me", 1);
Console.WriteLine(message.Raw);
Console.WriteLine(message.Payload.Body.Data);
You should try both out and see what works best for what you're trying to do.
To get message.Raw you need to pass a parameter, as stated in the docs:
Returned in messages.get and drafts.get responses when the format=RAW parameter is supplied.
If none of those things work, you could try iterating over the parts of the message to find your data:
foreach (var part in message.Payload.Parts)
{
byte[] data = Convert.FromBase64String(part.Body.Data);
string decodedString = Encoding.UTF8.GetString(data);
Console.WriteLine(decodedString);
}
I want to check whether a facebook user liked my facebook page or not. I got so many solutions using javascript but I want to implement this requirement in ASP.Net.
I copied the code from the below link:
http://duanedawnrae.com/Blog/post/2012/02/29/Determine-if-a-Facebook-user-Likes-your-page-with-ASPNET.aspx
I got the below ASP.Net code which works for the same.
ASP.Net code:
public class WebService : System.Web.Services.WebService
{
[WebMethod()]
public string GetFacebookLikeStatus(string fbpageid, string fbappid, string fbtoken, string fburl)
{
string strReturn = null;
// Placeholder for the Facbook "like" API call
string strURL = null;
strURL = "https://graph.facebook.com/me/likes?access_token=" + fbtoken;
// Placeholder for the Facebook GET response
WebRequest objGETURL = null;
objGETURL = WebRequest.Create(strURL);
// Declare response stream
Stream objStream = null;
// Declare The Facebook response
string strLine = null;
// Declare a count on the search term
int intStr = 0;
try
{
// Create an instance of the StreamReader
StreamReader objReader = new StreamReader(objStream);
// Get the response from the Facebook API as a JSON string.
// If access_token is not correct for the logged
// on user Facebook returns (400) bad request error
objStream = objGETURL.GetResponse().GetResponseStream();
// If all is well
try
{
// Execute the StreamReader
strLine = objReader.ReadToEnd().ToString();
// Check if Facebook page Id exists or not
intStr = strLine.IndexOf(fbpageid); // if valid return a value
if (intStr > 0)
{
strReturn = "1";
// if not valid return a value
}
else
{
strReturn = "0";
}
objStream.Dispose();
}
catch (Exception ex)
{
// For testing comment out for production
strReturn = ex.ToString();
// Uncomment below for production
//strReturn = "Some friendly error message"
}
}
catch (Exception ex)
{
// For testing comment out for production
strReturn = ex.ToString();
// Uncomment below for production
//strReturn = "Some friendly error message"
}
return strReturn;
}
}
The above code contains a webservice which contains a single function. The function contains four input parameters and returns a single output string.
But when I run this webservice I got the error, “Value cannot be null. Parameter name: stream”. This error is coming because the “objStream” variable is set to null. Please fix the issue so that I can get my correct output as I dont know how to implement my requirement.
Like Gating is not allowed on Facebook, and neither is incentivizing users to like your Page. Users must like something only because they really want to, you can´t reward them in any way.
That being said, you would need the user_likes permission to use /me/likes, and you would need to get it approved by Facebook. Which will not happen just for checking if the user liked your Page.
Btw, that article is from 2012. A lot of stuff changed since then.
One of my error message renders a link. However, Html.ValidationSummary() encodes it and therefore it displays as follow:
An account with the mobile or email you have specified already exists.
If you have forgotten your password, please Reset it.
Instead, it should render as:
An account with the mobile or email you have specified already exists.
If you have forgotten your password, please Reset it.
The error is added to the ModelState inside view as follows:
if (...)
{
ViewData.ModelState.AddModelError(string.Empty, string.Format("An account with the mobile or email you have specified already exists. If you have forgotten your password, please {0} it.", Html.ActionLink("Reset", "Reset")));
}
In short, how should I prevent Html.ValidationSummarry() to selectively/entirely encoding html in errors.
The current HTML helpers for displaying error messages do not support this. However, you could write your own HTML helpers that display the error message without HTML escaping it, i.e. they would treat the error message as raw HTML.
As a starting point, you could use the ASP.NET MVC source code from Codeplex, specifically the ValidationSummary method of the ValidationExtensions class:
public static string ValidationSummary(this HtmlHelper htmlHelper, string message, IDictionary<string, object> htmlAttributes) {
// Nothing to do if there aren't any errors
if (htmlHelper.ViewData.ModelState.IsValid) {
return null;
}
string messageSpan;
if (!String.IsNullOrEmpty(message)) {
TagBuilder spanTag = new TagBuilder("span");
spanTag.MergeAttributes(htmlAttributes);
spanTag.MergeAttribute("class", HtmlHelper.ValidationSummaryCssClassName);
spanTag.SetInnerText(message);
messageSpan = spanTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
}
else {
messageSpan = null;
}
StringBuilder htmlSummary = new StringBuilder();
TagBuilder unorderedList = new TagBuilder("ul");
unorderedList.MergeAttributes(htmlAttributes);
unorderedList.MergeAttribute("class", HtmlHelper.ValidationSummaryCssClassName);
foreach (ModelState modelState in htmlHelper.ViewData.ModelState.Values) {
foreach (ModelError modelError in modelState.Errors) {
string errorText = GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, null /* modelState */);
if (!String.IsNullOrEmpty(errorText)) {
TagBuilder listItem = new TagBuilder("li");
listItem.SetInnerText(errorText);
htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
}
}
}
unorderedList.InnerHtml = htmlSummary.ToString();
return messageSpan + unorderedList.ToString(TagRenderMode.Normal);
}
You can then change this method to treat the error message as raw HTML.
Two warnings though:
You're changing the meaning of certain properties of the ModelState class. While you get away with using your own HTML helpers now, a future version of ASP.NET MVC might introduce changes that no longer work with this approach.
Be very careful about not using error messages that aren't properly escaped so you don't expose your web app to XSS attacks. Certain standard validation annotation might not work any longer since they don't HTML escape the error message.