Having some trouble with the "GET" part of the Edit View, and can't really find anything online. So far, this is my POST section:
[HttpPost]
public ActionResult Edit(ContactsEditViewModel viewModel)
{
if (ModelState.IsValid)
{
var Contacts = TheContactContext.tblContacts.Find(viewModel.ID);
Contacts.Company = viewModel.Company;
Contacts.Contact = viewModel.Contact;
Contacts.Contact2 = viewModel.Contact2;
Contacts.Email1 = viewModel.Email1;
Contacts.Email2 = viewModel.Email2;
Contacts.IsSupplier = viewModel.IsSupplier;
Contacts.Telephone = viewModel.Telephone;
Contacts.Link = viewModel.Website;
Contacts.Notes = viewModel.Notes;
TheContactContext.SaveChanges();
return RedirectToAction("~/Contacts/Index");
}
return View(viewModel);
}
I've only ever done this using EntityFramework and letting it scaffold everything, so it's the first time using Viewmodels to do it personally.
Any help in whether my POST action is correct, and some guidance on the GET action would be appreciated :)
I believe you're on the right track with POST. GET is much more simplier:
public ActionResult Create()
{
return View(new ContactsCreateViewModel() { ... your initial settings, may be contained within constructor of view model directly ... });
}
The GET request requests server to provide empty form, which is filled by user, and filled data are sent back via POST, and processed within your provided function.
EDIT
If you are talking about Edit, then it is similar with one more step:
public ActionResult Edit(int id)
{
var data_model = TheContactContext.tblContacts.Get(id); // get model probably from database
var view_model = new ContactsCreateViewModel() {
Company = data_model.Company,
...
}; // copy all data into view model
return View(view_model); // and display view
}
When your page loads for a first time it sends GET request and retrieves model with collection of items from Db. After you've updated some of these items your app sends post request (most likely using Ajax) containing json data. You update your database in controller method and now it's time to refresh your page data. Simplest way is to use ajax.
$.ajax({
url: "http://" + location.host + "/CTRL/Action",
type: "POST",
data: yourdata,
}).done(function (html) {
location.reload(); (or other method to update UI)
}).fail(function (err) {
alert(err.statusText);
});
It's for client side. Server side is smth like :
lock (obj)
{
try
{
update database here...
}
catch(Exception ex)
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, ex.Message);
}
return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK, "Update completed");
}
Related
This is similar to a previous issue that was resolved earlier. In this case, instead of rendering a table in the same view, I'd like to take the data retrieved and push to a new view:
Populate child area paths in a multiselect dropdown list
Select some of the items in the dropdown list
Take the selected items (as area path children) send back to controller
From controller use area paths as parameters to a method retrieving work items
Take workitem list and populate list in new view
Here is my view script
function GetSelectedAreaPathChildren3() {
alert("TEST1");
var selectedAreaPathItems = '';
$("#AreaPathMultiSelectDropdownList :selected").each(function () {
selectedAreaPathItems += this.value + ";";
});
var selectedIterationPathItems = '';
$("#IterationPathMultiSelectDropdownList :selected").each(function () {
selectedIterationPathItems += this.value + ";";
});
console.log(selectedAreaPathItems);
$.ajax({
url: '#Url.Action("WorkItemTable", "PbcAzureDevOps")',
type: "POST",
data: { selectedAreaPathItems, selectedIterationPathItems },
success: function () {
alert("BLAH!");
}
});
}
Here is my controller method
public async Task<IActionResult> WorkItemTable(string selectedAreaPathItems, string selectedIterationPathItems)
{
//Get the retrieved work items
List<WorkItemInfo> retrievedWorkItems =
await GetAllSelectedWorkItems(selectedAreaPathItems, selectedIterationPathItems);
return View(retrievedWorkItems);
}
Expected result:
retrievedWorkItems is populated and sent to view ("WorkItemTable") -- after sending to view, "WorkItemTable is shown on screen
Actual result:
retrievedWorkItems is populated and sent to view ("WorkItemTable") -- after sending to view, "WorkItemTable is NOT SHOWN (i.e. WorkItemTable does not pop up)
I recognize from my research that I can't get the view to show up from the script and have also tried adding the following to the view:
#using (Html.BeginForm("WorkItemTable", "PbcAzureDevOps", FormMethod.Post))
{
}
Can anyone help me to get the WorkItemTable to render... I can already see the data in the foreach part of the view, it just doesn't show.
So I figured a workaround... instead of pulling the selections from the dropdownlists using Ajax, I pulled the data from the dropdown via IFormCollection:
public async Task<IActionResult> WorkItemTable(IFormCollection collection)
{
List<string> selectedAreaPathItems = collection["apchildrenDropDown"].ToList();
List<string> selectedIterationPathItems = collection["ipchildrenDropDown"].ToList();
//Get the retrieved work items
List<WorkItemInfo> retrievedWorkItems =
await GetAllSelectedWorkItems(selectedAreaPathItems, selectedIterationPathItems);
return View(retrievedWorkItems);
}
I have form that a user submits. For some reason, in our production environment when they click submit, the form is cleared and they lose all that they filled in when they click submit. I've been lost on this for awhile so any input would really help.
I've tried on multiple browsers and this occurs on each one (Chrome, Safari).
The first action creates the view model for the form, the second one takes that data/model and submits an application:
[Authorize(Roles = "Applicant")]
public IActionResult Application()
{
var vm = _applicantManager.GetApplicationViewModel(CurrentUser.UserName);
return View(vm);
}
[HttpPost]
//[ValidateAntiForgeryToken]
[Authorize(Roles = "Applicant")]
public IActionResult Application(ApplicationViewModel model)
{
var saved = false;
model = _applicantManager.RebuildApplicationViewModel(model);
if (ModelState.IsValid)
{
saved = _applicantManager.SubmitApplication(model, CurrentUser.UserName);
return RedirectToAction("Index");
}
return View(model);
}
I'm thinking if I remove the ValidateAntiForgeryToken that maybe this would solve issue, but am not sure.
Is it possible that the first action needs a route? On testing, it goes to the action with the HttpPost attribute when I click submit on my local environment.
Note: This is a problem on the production server, this does not occur on the local. This leads me to believe that may a possible IIS setting that needs changed?
JavaScript on the Page:
<script>
require(['jquery', 'jqueryui'], function($, jqueryui) {
$(function() {
$("#preHealthAreaDiv input:radio").click(function () {
var selectedVal = $("#preHealthAreaDiv input:radio:checked").val();
if (selectedVal == "Yes") {
$("#preHealthAreaDetail").show();
}
else {
$("#preHealthAreaDetail").hide();
}
})
});
});
</script>
$.ajax({
type: "POST",
url: "#Url.Action("SignInUp")",
data: JSON.stringify({ email_add: email_add ,}),
contentType: "application/json; charset=utf-8",
success: function (response) {
if (response.result == 'SignUp') {
alert("Opp`s its look like you dont have an access for this website");
window.location = response.Urls;
}
else
{
alert("Success fully login");
window.location = response.Url;
}
}
});
hi guys I`m new in mvc5 c# and i in counter this problem i want to hide my url parameter. any can help me thank you for advance
this is my code:
public ActionResult SingInUp(string email_add)
{
bool obj = db.tblUsers.Any(x => x.email_add.Equals(email_add));
if (obj)
{
tblUser user = db.tblUsers.Single(x => x.email_add == email_add);
Session["email_add"] = user.email_add;
Session["fname"] = user.fname;
Session["lname"] = user.lname;
return Json(new { result = "Redirect", Url = Url.Action("Check", "ProjectV3") });
}
else
{
return Json(new { result = "SingUp", Urls = Url.Action("SignUp", "ProjectV3", new { email_add = email_add}) });
}
}
This is i want to hide
If you want to effectively hide something from the client Url you will need to find a way to either mask it, or store it somewhere on the server that can be captured on the next request.
There are many places you can store this data on your server but really the obvious ones are.
Cookies
TempData
Now TempData may seem like the obvious choice as it persists across requests and is cleared from the TempData when accessed. Which is also its downfall, lets say you set the TempData in your SingUpIn method, then return the JsonResul which I am assuming is then used via JavaScript for a redirect. Then you redirect to this page and then pull the value of the TempData dictionary it is subsequently removed. So if the person ends up on the SingUp page and for some reasons decides to refresh the page the value in the TempData wont be found again.
Now this can be handled by resetting the TempData property on each read. So basically you read the TempData item then you reassign the TempData entry.
Here is some very basic code that [basically] works and doesnt show the email in the url.
public ActionResult SignUpIn(string email_acct)
{
//pretend i tested for a real user
TempData["email_acct"] = email_acct;
var r = new { result = "SingUp", Urls = Url.Action("SingUp") };
return Json(r);
}
public ActionResult SingUp()
{
if (!TempData.ContainsKey("email_acct"))
{
//no temp data email.. maybe redirect.. who knows!!
return RedirectToAction("Index");
}
//read the temp data entry..
string emailAcct = TempData["email_acct"].ToString();
//reset the temp data entry
TempData["email_acct"] = emailAcct;
return View(new SingUpModel { EmailAccount = emailAcct });
}
Unless you want to go to POST rather than URL parameters you are stuck. If you just want to hide some of the implementation details you could encode the parameter to obfuscate its meaning.
return Json(new { result = "SingUp", Urls = Url.Action("SignUp", "ProjectV3", new { email_add = Base64Encode(email_add)}) })
...
public static string Base64Encode(string plainText) {
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
You would end up with a URL like: http://localhost:1126/ProjectV3/SignUp?email_add=cGtleWJpcmQ5NUBnbWFpbC5jb20=. You could obviously change the name of the parameter to hide its intent.
I'm having this AngularJs http.post-function. In my view I have a list of Id:s. And when I click on any of these Id:s this function gets hit.
$scope.GoToSinglePost= function (id) {
console.log(id);
if (confirm("Go to blogPost with " + id + " ?")) {
$http.post("/Home/SingleBlogPost", { postId: id });
}
};
Everything works fine here and the post gets me to my mvc c# actionresult witch is this one below:
public ActionResult SingleBlogPost(int? postId)
{
var singlePost = _repo.GetSinglePost(postId);
var viewModel = new SingleBlogPostViewModel()
{
Post = singlePost
};
return View(viewModel);
}
In this ActionResult the postId i've sent from my angularPost gets in to the parameter int? postId
And the actionResult starts to render and it's if I debug it, I can see that it will go in to its view (SingleBlogPost.cshtml)
But what happens if I watch it in my browser, everything stays the same. I'm still in the same view where I was from the beginning. Why doesn't my SingleBlogPost Actionresult-view renders in the browser? Why I'm I still on the same page even though the SingleBlogPost-method gets hit and goes thuogh it's view when I debug?
//Thanks
try adding a success or then once the operation is complete to perform further actions there, something like:
$http.post("/Home/SingleBlogPost", { postId: id }).success(function(data) {
//data is your response from server to the request;
//do something with data here, like changing to correct view;
});
I have a form which a user can fill in x times with the data they want too. The form is posted to the following Action.
[HttpPost]
public ActionResult Manage(ProductOptionModel DataToAdd)
{
if (!ModelState.IsValid)
{
return View(DataToAdd);
}
var ProdServ = new ProductService();
if (DataToAdd.ID != 0)
{
//Edit Mode.
DataToAdd = ProdServ.EditProductOption(DataToAdd);
ViewData["Message"] = "Option Changes Made";
}else
{
//Add
DataToAdd = ProdServ.AddProductOption(DataToAdd);
ViewData["Message"] = "New Option Added";
}
var RetModel = new ProductOptionModel() {ProductID = DataToAdd.ProductID};
return View(RetModel);
}
So at the bottom I blank the model (Leaving just the required field) and then return to the view. However the view holds the data from the previously submitted form.
Any ideas why? I have debugged the code and checked that the RetModel variable is empty.
Html helpers work this way when a view is returned on HTTP POSTs. They prefer post data over model values.
Use Post/Redirect/Get
That's why I suggest you use the Post/Redirect/Get pattern that's very well supported in Asp.net MVC. Your controller actions should redirect to some GET action after POST has successfully completed as it is in your case.
public ActionResult Process()
{
return View(new Data { Id = -1 });
}
[HttpPost]
public ActionResult Process(Data data)
{
if (!this.ModelState.IsValid)
{
return View(data);
}
new MyService().ProcessData(data);
return RedirectToAction("Process");
}
And if you display all previously entered data you can provide those in in the GET action or transfer them from POST to GET action using TempData dictionary.
This is because the build in input helpers will look at the posted data first and use those values if they exist. Then it will look at the model.