I've been working on a website using ASP.NET MVC, in this website you can directly send an email to a specific email address. It's working properly, but the information being sent in the email (like Name, Email Address, ect.) don't have a database. So I tried adding a database for it, but somehow it's not working and I keep having some errors. I'm just new with this kind of stuff so I'm not sure if it's possible to send the email and at the same time save it to a database. I know there's something wrong with what I'm doing, so someone please help me. Thank you.
Here's my Controller for the sending of email:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(TalentInfo model, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
RegisterRepository regRepo = new RegisterRepository();
if (regRepo.Register(model))
{
List<string> paths = new List<string>();
foreach (var file in files)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
paths.Add(path);
}
}
var message = new MailMessage();
foreach (var path in paths)
{
var fileInfo = new FileInfo(path);
var memoryStream = new MemoryStream();
using (var stream = fileInfo.OpenRead())
{
stream.CopyTo(memoryStream);
}
memoryStream.Position = 0;
string fileName = fileInfo.Name;
message.Attachments.Add(new Attachment(memoryStream, fileName));
}
//Rest of business logic here
string EncodedResponse = Request.Form["g-Recaptcha-Response"];
bool IsCaptchaValid = (ReCaptcha.Validate(EncodedResponse) == "True" ? true : false);
if (IsCaptchaValid)
{
var body = "<p><b>Email From:</b> {0} ({1})</p><p><b>Message:<b></p><p>{2}</p>";
message.To.Add(new MailAddress("***#gmail.com")); // replace with valid value
message.From = new MailAddress("***#ymailcom"); // replace with valid value
message.Subject = "YesDubai.org (REGISTRATION)";
message.Body = string.Format(body, model.Talent_Name, model.Talent_Email, model.Talent_SelfPromotion);
message.IsBodyHtml = true;
using (var smtp = new SmtpClient())
{
var credential = new NetworkCredential
{
UserName = "***#gmail.com", // replace with valid value
Password = "***" // replace with valid value
};
smtp.Credentials = credential;
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.EnableSsl = true;
smtp.SendCompleted += (s, e) =>
{
//delete attached files
foreach (var path in paths)
System.IO.File.Delete(path);
};
await smtp.SendMailAsync(message);
ViewBag.Message = "Your message has been sent!";
ModelState.Clear();
return View("Register");
}
}
else
{
TempData["recaptcha"] = "Please verify that you are not a robot!";
}
} return View(model);
}
}
And here's the Modal class:
public partial class TalentInfo
{
[Display(Name = "ID")]
public int TalentID { get; set; }
[Display(Name = "Talent's Name")]
public string Talent_Name { get; set; }
[Display(Name = "Email Address")]
public string Talent_Email { get; set; }
[Display(Name = "Self Promotion")]
public string Talent_SelfPromotion { get; set; }
}
And here's the Repository:
public class RegisterRepository
{
//SqlTransaction transaction = null;
private SqlConnection con;
//To Handle connection related activities
private void connection()
{
string constr = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();
con = new SqlConnection(constr);
}
internal bool Register(TalentInfo model)
{
throw new NotImplementedException();
connection();
try
{
SqlCommand com = new SqlCommand("SP_INSERT_TALENT_INFO", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Talent_name", model.Talent_Name);
com.Parameters.AddWithValue("#Talent_email", model.Talent_Email);
com.Parameters.AddWithValue("#Talent_SelfPromotion", model.Talent_SelfPromotion);
con.Open();
int i = com.ExecuteNonQuery();
con.Close();
if (i >= 1)
{
return true;
}
else
{
return false;
}
}
catch
{
return Register(model);
}
finally
{
con.Close();
}
}
}
This is simply a compile error. You need to return a result in all paths of your code.
You have a missing return here
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(TalentInfo model, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
//you have lots of code here....
}
else
{
//you need to return something here....because (ModelState.IsValid) might be false
}
}
There are 2 Errors in your code:
1) Return something when if (ModelState.IsValid) evaluates to false.
2) In the register method, remove this line :
throw new NotImplementedException();
Related
I'm trying to return a password from a foreach-loop to do some validations, but I can't get the password-variable to return. I keep getting errors. I do this in my controller.
My code:
[HttpPost]
public IActionResult Login(userModel user)
{
ViewBag.Password = pwd.GetPassword(user);
string password = "";
foreach(var pwdR in ViewBag.Password.Rows)
{
password = pwdR[1];
}
return password; // Here I get this error: CS0029: Cannot implicitly convert type 'string' to 'Microsoft.AspNetCore.Mvc.IActionResult'
// VALIDATION CODE
....................
}
What am I doing wrong?
Thank you!
UPDATE:
[HttpPost]
public IActionResult Login(userModel user)
{
ScryptEncoder enc = new ScryptEncoder();
UserModel pwd = new UserModel();
ViewBag.Password = pwd.GetPassword(user);
string password = "";
foreach(var pwdR in ViewBag.Password.Rows)
{
password = pwdR[1];
}
return password; // Here I get this error: CS0029: Cannot implicitly convert type 'string' to 'Microsoft.AspNetCore.Mvc.IActionResult'
// VALIDATION CODE
bool match = enc.Compare(user.pwd, password);
if (match)
{
ViewBag.Error = "You are now logged in.";
return View();
} else
{
ViewBag.Error = "Login failed.";
return View();
}
}
It is a big performance bug to load all users and to find one you need.
Try this code
[HttpPost]
public IActionResult Login(UserModel user)
{
ScryptEncoder enc = new ScryptEncoder();
var userNamePassword= GetUserNamePassword (user) ;
if( userNamePassword==null)
ViewBag.Error = "Login failed. User is not found";
return View();
}
// VALIDATION CODE
bool match = enc.Compare(userNamePassword.Password, password);
if (match)
{
ViewBag.Error = "You are now logged in.";
return View();
} else
{
ViewBag.Error = "Login failed.";
return View();
}
}
change your model class to this
public class UserNamePasswordModel
{
public string Username { get; set; }
public string Password { get; set; }
}
and place this code somewhere near the Login action
private UserNamePasswordModel GetUserNamePassword (UserModel user)
{
UserNamePasswordModel userNamePassword= null;
var connectionString = "Server=localhost;Database=xxxx; uid = xxxx;Password=xxxx;";
using (var connection = new MySqlConnection(connectionString))
{
var command = new MySqlCommand("SELECT UserName, Password FROM User WHERE Username = #Username", connection);
command.Parameters.AddWithValue("#Username", user.Username);
connection.Open();
var reader = command.ExecuteReader();
if (reader.HasRows)
{
if reader.Read()
{
userNamePassword= new UserNamePasswordModel
{
Username= reader.GetString(0),
Password = reader.GetString(1)
};
}
}
reader.Close();
}
}
return userNamePassword;
}
try returning Ok with password in it, something like: return Ok(password);
I am using ASP.NET MVC Core 3.1 and I have to send files as an email attachment using SmtpClent using the below code.
I want to store the posted files to an Attachments property in Message.cs class and I want to pass this class to SendEmail method. When I send email using EmailSender class's SendEmail method, I do receive "Cannot access a closed Stream." I think I am making mistake to put values to the Attachments property of the Message.cs. Could you please help me on how to do this correctly?
HomeController.cs
[HttpPost]
public async Task<IActionResult> Index(string id)
{
var files = Request.Form.Files.Any() ? Request.Form.Files : new FormFileCollection();
List<string> recipients = new List<string>
{ "abc#gmail.com",
"xyz#gmail.com"};
_emailSender.SendEmail(new Message(recipients, "Test Subject", "<h1>Welcome</h2>", files));
return View();
}
Message.cs
public class Message
{
public List<string> Recipients { get; set; }
public string Subject { get; set; }
public string Content { get; set; }
public List<Attachment> Attachments { get; set; }
public Message(IEnumerable<string> to, string subject, string content, IFormFileCollection attachments)
{
Recipients = new List<string>();
Attachments = new List<Attachment>();
Recipients.AddRange(to.Select(x => x));
Subject = subject;
Content = content;
foreach(var file in attachments)
{
Attachments.Add(new Attachment(file.OpenReadStream(), file.FileName));
}
}
}
EmailSender.cs
public class EmailSender
{
public void SendEmail(Message message)
{
Task.Factory.StartNew(() =>
{
SendMailAsync(message);
});
}
private async void SendMailAsync(Message message)
{
try
{
using (MailMessage mailMessage = new MailMessage())
{
mailMessage.IsBodyHtml = true;
mailMessage.Subject = message.Subject;
mailMessage.SubjectEncoding = Encoding.UTF8;
mailMessage.Body = message.Content;
mailMessage.BodyEncoding = Encoding.UTF8;
mailMessage.From = new MailAddress("From email");
foreach (var recipient in message.Recipients)
{
mailMessage.To.Add(new MailAddress(recipient));
}
if (message.Attachments != null && message.Attachments.Any())
{
foreach (var attachment in message.Attachments)
{
mailMessage.Attachments.Add(attachment);
}
}
using (SmtpClient smtpClient = new SmtpClient("Host name", 587))
{
NetworkCredential smtpUserInfo = new NetworkCredential("UserName", "Password");
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = smtpUserInfo;
await smtpClient.SendMailAsync(mailMessage);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendMailAsync exception: " + ex);
}
finally
{
Console.WriteLine("SendMailAsync done");
}
}
}
Copy your files to MemoryStreams, so they don't go out of scope when request ends
var files = Request.Form.Files.Any() ? Request.Form.Files : new FormFileCollection();
var filesInStreams = files.Select(x =>
{
var ms = new MemoryStream();
x.CopyTo(ms);
return (ms, x.FileName);
}).ToList();
_emailSender.SendEmail(new Message(recipients, "Test Subject", "<h1>Welcome</h2>", filesInStreams));
You will need to adjust Message constructor as well
public class Message
{
public List<string> Recipients { get; set; }
public string Subject { get; set; }
public string Content { get; set; }
public List<Attachment> Attachments { get; set; }
public Message(IEnumerable<string> to, string subject, string content, List<(Stream stream, string fileName)> attachments)
{
Recipients = new List<string>();
Attachments = new List<Attachment>();
Recipients.AddRange(to.Select(x => x));
Subject = subject;
Content = content;
foreach (var file in attachments)
{
Attachments.Add(new Attachment(file.stream, file.fileName));
}
}
}
I have created a web service to send emails from a Winform application.
The data is sent as a BYTE[] but only works with the array being under 3mb. Within the Web config and App Config I have increased maxAllowedContentLength to their limit. This is the line that fails: HttpWebResponse oWebResp = myReq.GetResponse() as HttpWebResponse;
Here is the SMTP Web service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Mail;
using System.Configuration;
using System.IO;
namespace SMTPWebService.Models
{
public class Mailer : IMailer
{
public void SendMail(EmailContentDto emailContentDto)
{
MailMessage mail = new MailMessage(emailContentDto.Sender,
emailContentDto.Recipient);
SmtpClient client = new SmtpClient();
client.Port = Convert.ToInt32(ConfigurationManager.AppSettings["SMTPServerPort"]);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Timeout = 80000;
client.Host = ConfigurationManager.AppSettings["SMTPServerAddress"];
mail.Subject = emailContentDto.Subject;
mail.Body = emailContentDto.HtmlBody;
mail.IsBodyHtml = true;
if (emailContentDto.FileBinary != null)
mail.Attachments.Add(
new Attachment(
new MemoryStream(emailContentDto.FileBinary),
emailContentDto.FileName,
emailContentDto.FileFormat));
try
{
client.Send(mail);
}
catch (Exception)
{
throw;
}
}
}
}
Here is the Winform wending the data:
public void SendEmail(String sender, String recipient, String subject, String htmlBody, String fileLocation, String AttachemntNewName)
{
var stFileName = "";
var stFileExt = "";
byte[] buffer = null;
String key_ = "";
if (!String.IsNullOrEmpty(fileLocation))
{
FileStream st = new FileStream(fileLocation, FileMode.Open);
stFileName = st.Name;
stFileExt = Path.GetExtension(stFileName.ToLower());
buffer = new byte[st.Length];
st.Read(buffer, 0, (int)st.Length);
st.Close();
key_ = MimeTypesAutoGet(stFileExt);
};
EmailDto emailDto = new EmailDto()
{
Sender = sender,
Recipient = recipient,
Subject = subject,
HtmlBody = htmlBody,
FileBinary = buffer,
FileFormat = key_,
FileName = stFileName // AttachemntNewName
};
String apiUrl = "http://ADDRESS_TO_SERVER";
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(apiUrl);
byte[] reqBytes = System.Text.UTF8Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(emailDto));
myReq.SendChunked = true;
myReq.AllowWriteStreamBuffering = false;
myReq.KeepAlive = true;
myReq.Timeout = 30000;
myReq.Credentials = CredentialCache.DefaultCredentials;
myReq.ContentLength = reqBytes.Length;
myReq.Method = "POST";
// myReq.ContentType = "multipart/form-data";
myReq.ContentType = "application/json";
Stream oReqStream = myReq.GetRequestStream();
oReqStream.Write(reqBytes, 0, reqBytes.Length);
string StringByte = BitConverter.ToString(reqBytes);
try
{
HttpWebResponse oWebResp = myReq.GetResponse() as HttpWebResponse;
}
catch (WebException Ex)
{
MessageBox.Show(Ex.ToString());
}
}
This is the DTO:
public class EmailContentDto
{
public String Recipient { get; set; }
public String Sender { get; set; }
public String Subject { get; set; }
public String HtmlBody { get; set; }
public Byte[] FileBinary { get; set; }
public String FileFormat { get; set; }
public String FileName { get; set; }
}
Here is the Controller:
public class HomeController : Controller
{
private IMailer _mailer = new Mailer();
public ActionResult Index()
{
return View();
}
public ActionResult SendMail([FromBody]EmailContentDto emailContentDto)
{
_mailer.SendMail(emailContentDto);
return null;
}
}
I have need to import upwards of 35,000 Codes for a campaign from an excel spreadsheet. I have the following code below (which works in exactly the way i need it to) but when i run the process it can take over 20-30 mins to complete.
If there is anything that can be done to help speed up the process that would be greatly appreciated. I wouldn't call myself a advanced programmer and i know this could probably be done with advance coding techniques. If someone could point me in the right direction that would be greatly appreciated.
The models for the campaign and mastercode tables.
public class Campaign
{
public int CampaignId { get; set; }
public string Name { get; set; }
public virtual List<MasterCode> MasterCodes { get; set; }
}
public class MasterCode
{
public int MasterCodeId { get; set; }
public int CampaignId { get; set; }
public virtual Campaign Campaign { get; set; }
public string Code { get; set; }
public bool Used { get; set; }
public DateTime SubmittedOn { get; set; }
}
The following is the code in the view. The form fields are not model bound as this code is in a popup window on a view that is already model bound to another model.
#using (Html.BeginForm("UploadMasterCodes", "Campaigns", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.Hidden("CampaignId", Model.CampaignId)
<div class="form-group">
#Html.Label("Master Code File")
#Html.TextBox("File", null, new { type = "file", #class = "form-control" })
</div>
}
Controller Code
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadMasterCodes(CampaignMasterCodeUploadViewModel model)
{
if (ModelState.IsValid)
{
var result = CampaignMethods.uploadMasterCodes(model.File, model.CampaignId);
TempData["SuccessMessage"] = result;
return RedirectToAction("Details", new { id = model.CampaignId });
}
return RedirectToAction("Details", new { id = model.CampaignId });
}
And finally here is the code that performs the upload to the database. I am building a string that will track any errors that happen as i need to know of them all.
public static string uploadMasterCodes(HttpPostedFileBase file, int campaignId)
{
using (ApplicationDbContext _context = new ApplicationDbContext())
{
string response = string.Empty;
var campaign = _context.Campaigns.Find(campaignId);
if (campaign == null)
{
return String.Format("Campaign {0} not found", campaignId.ToString());
}
var submitDate = DateTime.Now;
int successCount = 0;
int errorCount = 0;
if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName))
{
byte[] fileBytes = new byte[file.ContentLength];
var data = file.InputStream.Read(fileBytes, 0, Convert.ToInt32(file.ContentLength));
using (var package = new ExcelPackage(file.InputStream))
{
var currentSheet = package.Workbook.Worksheets;
var workSheet = currentSheet.First();
var noOfRow = workSheet.Dimension.End.Row;
for (int i = 1; i <= noOfRow; i++)
{
var masterCode = new MasterCode();
masterCode.Code = workSheet.Cells[i, 1].Value.ToString();
masterCode.CampaignId = campaignId;
masterCode.Campaign = campaign;
masterCode.SubmittedOn = submitDate;
// Check to make sure that the Code does not already exist.
if (!campaign.MasterCodes.Any(m => m.Code == masterCode.Code))
{
try
{
_context.MasterCodes.Add(masterCode);
_context.SaveChanges();
successCount++;
}
catch (Exception ex)
{
response += String.Format("Code: {0} failed with error: {1} <br />", masterCode.Code, ex.Message);
errorCount++;
}
}
else
{
response += String.Format("Code: {0} already exists <br />", masterCode.Code);
errorCount++;
}
}
response += string.Format("Number of codes:{0} / Success: {1} / Errors {2}", noOfRow.ToString(), successCount.ToString(), errorCount.ToString());
}
}
return response;
}
}
Whenever I need to read an Excel file I use this OLEDB provider:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source={FilePath};Extended Properties='Excel 12.0 Xml;HDR=Yes;IMEX=1';
(More information on this topic can be found here and here)
Then you could do a bulk insert for the quickest insert.
See this answer how to do this in memory. In your case you'll first need to save the file somewhere on the server, process and report progress to the user.
On the suggestion of #grmbl, and lots of reading, I was able to solve the speed issue using SQLBulkCopy. I didn't use the OLEDB provider but instead copied the file to the server and created a datatable. Which i then used for the bulk copy. The following code got the runtime down to around 10 seconds for 335,000 records.
I have cut out all error checking code so its not a wall of code.
The controller code.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadMasterCodes(CampaignMasterCodeUploadViewModel model)
{
if (ModelState.IsValid)
{
var filename = Path.GetFileName(model.File.FileName);
var path = FileMethods.UploadFile(model.File, Server.MapPath("~/App_Data/Bsa4/"), filename);
var dt = CampaignMethods.ProcessMasterCodeCsvToDatatable(path, model.CampaignId);
TempData["SuccessMessage"] = CampaignMethods.ProcessMastercodeSqlBulkCopy(dt);
return RedirectToAction("Details", new { id = model.CampaignId });
}
TempData["ErrorMessage"] = "Master code upload form error. Please refresh the page and try again.";
return RedirectToAction("Details", new { id = model.CampaignId });
}
The processing code.
public static DataTable ProcessMasterCodeCsvToDatatable(string file, int campaignId)
{
using (ApplicationDbContext _context = new ApplicationDbContext()) {
var campaign = _context.Campaigns.Find(campaignId);
DataTable dt = new DataTable();
dt.Columns.Add("CampaignId");
dt.Columns.Add("Code");
dt.Columns.Add("Used");
dt.Columns.Add("SubmittedOn");
string line = null;
var submitDate = DateTime.Now;
using (StreamReader sr = File.OpenText(file))
{
while ((line = sr.ReadLine()) != null)
{
string[] data = line.Split(',');
if (data.Length > 0)
{
if (!string.IsNullOrEmpty(data[0]))
{
DataRow row = dt.NewRow();
row[0] = campaign.CampaignId;
row[1] = data[0];
row[2] = false;
row[3] = submitDate;
dt.Rows.Add(row);
}
}
}
}
return dt;
}
}
public static String ProcessMastercodeSqlBulkCopy(DataTable dt)
{
string Feedback = string.Empty;
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
cn.Open();
using (SqlBulkCopy copy = new SqlBulkCopy(cn))
{
copy.ColumnMappings.Add(0, "CampaignId");
copy.ColumnMappings.Add(2, "Code");
copy.ColumnMappings.Add(3, "Used");
copy.ColumnMappings.Add(4, "SubmittedOn");
copy.DestinationTableName = "MasterCodes";
try
{
//Send it to the server
copy.WriteToServer(dt);
Feedback = "Master Code Upload completed successfully";
}
catch (Exception ex)
{
Feedback = ex.Message;
}
}
}
return Feedback;
}
I am trying to POST some data using HTTPClient. I have managed to use the following code when simply getting data in JSON format, but it doesn't seem to work for a POST.
This is the code I'm using:
public static async Task<SwipeDetails> SaveSwipesToCloud()
{
//get unuploaded swips
IEnumerable<SwipeDetails> swipesnotsved = SwipeRepository.GetUnUploadedSwipes();
foreach (var item in swipesnotsved)
{
//send it to the cloud
Uri uri = new Uri(URL + "SaveSwipeToServer" + "?locationId=" + item.LocationID + "&userId=" + item.AppUserID + "&ebCounter=" + item.SwipeID + "&dateTimeTicks=" + item.DateTimeTicks + "&swipeDirection=" + item.SwipeDirection + "&serverTime=" + item.IsServerTime );
HttpClient myClient = new HttpClient();
var response = await myClient.GetAsync(uri);
//the content needs to update the record in the SwipeDetails table to say that it has been saved.
var content = await response.Content.ReadAsStringAsync();
}
return null;
}
This is the method it's trying to contact. As you can see, the method also returns some data in JSON format so as well as a POST it's also getting some data back which I need to be able to work with:
[HttpPost]
public JsonResult SaveSwipeToServer(int locationId, int userId, int ebCounter, long dateTimeTicks, int swipeDirection, int serverTime)
{
bool result = false;
string errMsg = String.Empty;
int livePunchId = 0;
int backupPunchId = 0;
IClockPunch punch = null;
try
{
punch = new ClockPunch()
{
LocationID = locationId,
Swiper_UserId = userId,
UserID = ebCounter,
ClockInDateTime = DateTimeJavaScript.ConvertJavascriptDateTime(dateTimeTicks),
ClockedIn = swipeDirection.Equals(1),
};
using (IDataAccessLayer dal = DataFactory.GetFactory())
{
DataAccessResult dalResult = dal.CreatePunchForNFCAPI(punch, out livePunchId, out backupPunchId);
if (!dalResult.Result.Equals(Result.Success))
{
throw dalResult.Exception;
}
}
result = true;
}
catch (Exception ex)
{
errMsg = "Something Appeared to go wrong when saving punch information to the horizon database.\r" + ex.Message;
}
return Json(new
{
result = result,
punchDetails = punch,
LivePunchId = livePunchId,
BackUpPunchId = backupPunchId,
timeTicks = DateTimeJavaScript.ToJavaScriptMilliseconds(DateTime.UtcNow),
errorMessage = errMsg
}
,JsonRequestBehavior.AllowGet);
}
At the moment the data being stored in 'content' is just an error message.
You can post the parameters in the body of the request.
public static async Task<SwipeDetails> SaveSwipesToCloud() {
//get unuploaded swips
var swipesnotsved = SwipeRepository.GetUnUploadedSwipes();
var client = new HttpClient() {
BaseAddress = new Uri(URL)
};
var requestUri = "SaveSwipeToServer";
//send it to the cloud
foreach (var item in swipesnotsved) {
//create the parameteres
var data = new Dictionary<string, string>();
data["locationId"] = item.LocationID;
data["userId"] = item.AppUserID;
data["ebCounter"] = item.SwipeID;
data["dateTimeTicks"] = item.DateTimeTicks;
data["swipeDirection"] = item.SwipeDirection;
data["serverTime"] = item.IsServerTime;
var body = new System.Net.Http.FormUrlEncodedContent(data);
var response = await client.PostAsync(requestUri, body);
//the content needs to update the record in the SwipeDetails table to say that it has been saved.
var content = await response.Content.ReadAsStringAsync();
}
return null;
}
I am not sure how you host your service, it is not clear from your code. I hosted mine in Web API controller SwipesController in application HttpClientPostWebService. I don't suggest to use JsonResult. For mobile client I would just return the class you need.
You have 2 options:
Use get not post.
Use post.
Both cases are below
Controller:
namespace HttpClientPostWebService.Controllers
{
public class SwipesController : ApiController
{
[System.Web.Http.HttpGet]
public IHttpActionResult SaveSwipeToServer(int locationId, int userId, int ebCounter, long dateTimeTicks, int swipeDirection, int serverTime)
{
return Ok(new SwipeResponse
{
TestInt = 3,
TestString = "Testing..."
});
}
[System.Web.Http.HttpPost]
public IHttpActionResult PostSwipeToServer([FromBody] SwipeRequest req)
{
return Ok(new SwipeResponse
{
TestInt = 3,
TestString = "Testing..."
});
}
}
public class SwipeRequest
{
public string TestStringRequest { get; set; }
public int TestIntRequest { get; set; }
}
public class SwipeResponse
{
public string TestString { get; set; }
public int TestInt { get; set; }
}
}
Client:
async private void Btn_Clicked(object sender, System.EventArgs e)
{
HttpClient client = new HttpClient();
try
{
var result = await client.GetAsync(#"http://uri/HttpClientPostWebService/Api/Swipes?locationId=1&userId=2&ebCounter=3&dateTimeTicks=4&swipeDirection=5&serverTime=6");
var content = await result.Content.ReadAsStringAsync();
var resp = JsonConvert.DeserializeObject<SwipeResponse>(content);
}
catch (Exception ex)
{
}
try
{
var result1 = await client.PostAsync(#"http://uri/HttpClientPostWebService/Api/Swipes",
new StringContent(JsonConvert.SerializeObject(new SwipeRequest() { TestIntRequest = 5, TestStringRequest = "request" }), Encoding.UTF8, "application/json"));
var content1 = await result1.Content.ReadAsStringAsync();
var resp1 = JsonConvert.DeserializeObject<SwipeResponse>(content1);
}
catch (Exception ex)
{
}
}