How to get a Json Response after saving a data in ASP.Net - asp.net

how can I get a response after I created a data? So I want is when is saves. it show it's response, maybe in messagebox? Is it possible do it?
This is my controller code in saving..
[HttpPost]
[ValidateAntiForgeryToken]
public async System.Threading.Tasks.Task<ActionResult> Create(FormCollection formCollection, string fn, string ln , ParentModel apsp)
{
string username = "sa";
string apiKey = "sa";
string baseUrl = "https://sandbox-api.paysimple.com";
var settings = new PaySimpleSdk.Models.PaySimpleSettings(apiKey, username, baseUrl);
var paymentService = new PaymentService(settings);
fn = apsp.Customer.FirstName;
ln = apsp.Customer.LastName;
string street1 = apsp.Customer.BillingAddress.StreetAddress1;
string street2 = apsp.Customer.BillingAddress.StreetAddress2;
string city = apsp.Customer.BillingAddress.City;
Enum statecode = apsp.Customer.BillingAddress.StateCode;
Enum country = apsp.Customer.BillingAddress.Country;
string zipcode = apsp.Customer.BillingAddress.ZipCode;
string credit = apsp.CreditCard.CreditCardNumber;
string expir = apsp.CreditCard.ExpirationDate;
Enum issuer = apsp.CreditCard.Issuer;
decimal amount = apsp.Payment.Amount;
string ccv = apsp.Payment.Cvv;
var customerPayment = new NewCustomerPayment<CreditCard>
{
Customer = new Customer()
{
FirstName = fn,
LastName = ln,
BillingAddress = new Address
{
StreetAddress1 = street1,
StreetAddress2 = street2,
City = city,
StateCode = (StateCode)statecode,
Country = (CountryCode)country,
ZipCode = zipcode
}
},
Account = new CreditCard
{
CreditCardNumber = credit,
ExpirationDate = expir,
Issuer = (Issuer)issuer
},
Payment = new Payment
{
Amount = amount,
Cvv = ccv
}
};
var newCustomerPayment = await paymentService.CreateNewCustomerPaymentAsync(customerPayment);
return RedirectToAction("Index");
}
The function of creating a data is from the SDK and the model itself

You have 2 options:
Create action should return JsonResult instead of redirect. But you will need to use AJAX when calling Create action.:
public async System.Threading.Tasks.Task<ActionResult> Create(FormCollection formCollection, string fn, string ln , ParentModel apsp)
{
/// your code for creating object
return Json(newCustomerPayment, JsonRequestBehavior.AllowGet);
}
on the client side use Ajax.BeginForm instead of Html.BeginForm
using (Ajax.BeginForm("Create", Home , new AjaxOptions { HttpMethod = "POST", OnSuccess = "customerPaymentCreatedSuccess" }))
{
}
<script>
function customerPaymentCreatedSuccess(response)
{
alert(JSON.stringify(response, null, 4));
}
</script>
Use Post/Redirect/Get pattern. Once new payment is created, store it in TempData
and return redirect as you currently do:
TempData["newCustomerPayment"] = newCustomerPayment;
return RedirectToAction("Index");
Then in Index Action check if there is anything in TempData and if there is, pass it to the view
public ActionResult Index()
{
var customerPayment = TempData["newCustomerPayment"] as NewCustomerPayment;
if(customerPayment != null)
{
ViewBag.customerPayment = customerPayment;
}
//other code..
}
Index view - generate JavaScript code to display customerPayment:
#{var customerPayment = ViewBag.customerPayment as NewCustomerPayment;}
#if(customerPayment != null)
{
<script>
alert("#Html.Raw(JsonConvert.SerializeObject(customerPayment ))");
</script>
}

To show an feedback of your of your operation you could return a JsonResult from your method and make the call and create the message box browser-side via Javascript.
Actions to take
1)change ActionResult to JsonResult in method definition
public async System.Threading.Tasks.Task<JsonResult> Create(FormCollection formCollection, string fn, string ln , ParentModel apsp)
2)change the return to something like:
return this.Json(message)
3)make your call to the method using ajax an create the message box on the callback method

Related

Get the Result from a list of Task

I know this has been asked before, but I simply cannot figure out how to do this right.
So, the below code is obviously wrong in the sense that I am awaiting something in a query.
// GET: /<controller>/
[HttpGet]
public new IActionResult Index()
{
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
model = _userManager.Users.Select(u => new Models.ViewModels.ApplicationUser.ListViewModel
{
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
return View(model);
}
This makes the following error show: "the "await" operator can only be used within an async lambda expression".
So, I finalize the query first and I make the lambda async:
// GET: /<controller>/
[HttpGet]
public new IActionResult Index()
{
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
// get users first, so I don't have to async something in a Select
var users = _userManager.Users.ToList();
// make the lambda asyc
model = users.Select(async u => new Models.ViewModels.ApplicationUser.ListViewModel
{
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
return View(model);
}
But then I get Cannot implicitly convert type 'System.Collections.Generic.List<System.Threading.Tasks.Task<Models.ViewModels.ApplicationUser.ListViewModel>>' to 'System.Collections.Generic.List<Models.ViewModels.ApplicationUser.ListViewModel>'
So basically (I guess) it says I have a list of Task of which I should get the result. But how do I get the result from this Task? Or better: what is the best way to go about this?
I've checked this and this and this without getting closer.
Your variable named model is of the type List<Task<ApplicationUser>>. To get a List<ApplicationUser> you just need to await all of the tasks. Also, right now the call to get all users is the blocking variant you can switch that out for ToListAsync. Try this instead:
[HttpGet]
public async Task<IActionResult> Index() {
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
// get users first, so I don't have to async something in a Select
var users = await _userManager.Users.ToListAsync();
// make the lambda asyc
modelTasks = users.Select(async u => new Models.ViewModels.ApplicationUser.ListViewModel {
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
var users = await Task.WhenAll(modelTasks);
return View(users);
}

How to get all url parameters in asp.net mvc?

My test url:
localhost:61578/?type=promotion&foo=bar
I usually use this way to get the value of type parameter:
public IActionResult Index(string type)
{
// type = "promotion"
}
My question: How to detect all parameters in the url? I want to prevent to access the page with some unknown parameter.
Something like this:
public IActionResult Index(string type, string foo)
{
if (!string.IsNullOrEmpty(foo))
{
return BadRequest(); // page 404
}
}
The problem is: I don't know exactly the name what user enters. So, it can be:
localhost:61578/?bar=baz&type=promotion
You can use the HttpContext Type to grab the query string
var context = HttpContext.Current;
then, you can grab the entire query string:
var queryString = context.Request.QueryString
// "bar=baz&type=promotion"
or, you can get a list of objects:
var query = context.Request.Query.Select(_ => new
{
Key = _.Key.ToString(),
Value = _.Value.ToString()
});
// { Key = "bar", Value = "baz" }
// { Key = "type", Value = "promotion" }
or, you could make a dictionary:
Dictionary<string, string>queryKvp = context.Request.GetQueryNameValuePairs()
.ToDictionary(_=> _.Key, _=> _.Value, StringComparer.OrdinalIgnoreCase);
// queryKvp["bar"] = "baz"
// queryKvp["type"] = "promotion"

Redirecting to the correct page after submitting a form in ASP.NET MVC

I have the same
#Html.ActionLink("SUSPEND", "Suspend", "Serials", new { id = s.serial, orderId = s.Order.orderID }, null)
on two different pages.
Let's say I can click on it from this page:
http://localhost:55058/Customers/Details/4106
and from this page:
http://localhost:55058/Orders/Details/102091
The link takes me to a form associated to two standard Controller actions, GET:
public ActionResult Suspend(string id, string orderId)
{
Serial serial = context.Serials.Single(x => x.serialID == id);
ViewBag.orderId = orderId;
return View(serial);
}
and POST:
[HttpPost]
public ActionResult Suspend(Serial serial, string orderId)
{
if (ModelState.IsValid)
{
serial.suspended = true;
serial.suspensionDate = DateTime.Now;
context.Entry(serial).State = EntityState.Modified;
context.SaveChanges();
ViewBag.orderId = orderId;
return View(context.Serials.Single(x => x.serialID == serial.serialID));
}
}
How do I Redirect() to the page where I first clicked the link, once I submitted the form? Possibly, in an elegant way...
Thanks.

Accessing the returned XML from an API call

I have the following action method to perform an API call:-
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Rack rack, FormCollection formValues)
{
if (ModelState.IsValid) {
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
foreach (string key in formValues)
{
query[key] = this.Request.Form[key];
}
query["username"] = "testuser";
query["password"] = ///.....
query["assetType"] = "Rack";
query["operation"] = "AddAsset";
var url = new UriBuilder("http://win-spdev:8400/servlets/AssetServlet");
url.Query = query.ToString();
try
{
string xml = client.DownloadString(url.ToString());
}
The return XML from the API call looks as follow:-
<operation>
<operationstatus>Failure</operationstatus>
<message>Rack already exists.Unable to add</message>
</operation>
but how i can reach the message and operationstaus and according to them to display an appropriate message . i use to serialize the returned Json such as , but i am not sure how to do so for the xML:-
var serializer = new JavaScriptSerializer();
var myObject = serializer.Deserialize<newprocess>(json);
string activityid = myObject.activityId;
Just load it into an XmlDocument.
Untested and from the top of my head:
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(theXML);
var status = xmlDoc.SelectSingleNode("/operation/operationstatus").InnerText;
var message = xmlDoc.SelectSingleNode("/operation/message").InnerText;
If you using ASP.NET mvc, I believe you can use HttpClient, instead of WebClient:
Define result class:
public class operation
{
public string operationstatus{get;set;}
public string message{get;set;}
}
And then use it for automatic deserilization:
var client = new HttpClient();
var result = client.PostAsync(url,
new FormUrlEncodedContent(new Dictionary<string, string>{
{"username","testuser"},
{"assetType","Rack"}}))
.Result.Content
.ReadAsAsync<operation>().Result;

Pass a value from controller to view

I have a problem in passing a value from controller to view
In controller, In the edit method
public ActionResult Edit( FormCollection form)
{
var id = Int32.Parse(form["CustomerServiceMappingID"]);
var datacontext = new ServicesDataContext();
var serviceToUpdate = datacontext.Mapings.First(m => m.CustomerServiceMappingID == id);
TryUpdateModel(serviceToUpdate, new string[] { "CustomerID", "ServiceID", "Status" }, form.ToValueProvider());
if (ModelState.IsValid)
{
try
{
var qw = (from m in datacontext.Mapings
where id == m.CustomerServiceMappingID
select m.CustomerID).First();
ViewData["CustomerID"] = qw;
datacontext.SubmitChanges();
//return Redirect("/Customerservice/Index/qw");
return RedirectToAction("Index", new { id = qw });
}
catch{
}
}
return View(serviceToUpdate);
}
Now in edit's view , I used this
#Html.Encode(ViewData["CustomerID"])
This is my Index method
public ActionResult Index(int id)
{
var dc = new ServicesDataContext();
var query = (from m in dc.Mapings
where m.CustomerID == id
select m);
// var a = dc.Customers.First(m => m.CustomerId == id);
// ViewData.Model = a;
// return View();
return View(query);
}
But the customerID on the page turns to be null.. Can u let me know if this procedure is correct?
You don't need to requery the id. Just use the id directly:
if (ModelState.IsValid)
{
datacontext.SubmitChanges();
//return Redirect("/Customerservice/Index/qw");
return RedirectToAction("Index", new { id = id});
}
Since you are redirecting the ViewData["CustomerID"] will be lost.
However the id in your Index method should be valid.
If your Index View requires the ViewData["CustomerID"] set it in your Index action:
public ActionResult Index(int id)
{
ViewData["CustomerID"] = id;
//....
I'm a bit confused as to which view does not have access to ViewData["CustomerId"]. If it's the Index view, you should set ViewData["CustomerId"] = id there.

Resources