Postback for the second time from asp.net MVC view - asp.net-mvc

Setup:
I am working on reset password page and planning to have a single view to display three forms one after another.
Initially user will be asked to enter username, then the form gets submitted.
I am able to capture it is HttpPost action method.
I am returning the same view but this time I am rendering a different form, I am doing this using Razor
When I try to submit (calling a different action method) from the second form that I am displaying now I am getting and error saying that Resource cannot be found
Question:
Is it not possible to post back twice from the sample page/view?
If possible how can I achieve it?
CSHTML:
#if (ViewBag.step == 1) {
<form id="frmUsername" action="#Url.Content("~/Account/ValidateAnswers")" method="post" novalidate="novalidate" ng-init="initStep1()">
...
</form>
}
#if (ViewBag.step == 2) {
<form action="#Url.Content("~/Account/ValidateUsername")" id="frmQuestions" ng-init="initStep2()" novalidate="novalidate">
...
</form>
}
Controller methods:
public ActionResult RecoverPassword(string userType)
{
ViewBag.step = 1;
ViewBag.userType = userType;
ViewBag.showUsernameErrorMessage = "false";
return View();
}
[AllowAnonymous]
[HttpPost]
public ActionResult ValidateUsername(string userName, string selectedUserType)
{
...
ViewBag.step = responseStep;
ViewBag.showUsernameErrorMessage = responseShowUsernameErrorMessage;
ViewBag.userName = userName;
ViewBag.userType = selectedUserType;
return View("~/Views/Account/RecoverPassword.cshtml");
}
[HttpPost]
public ActionResult ValidateAnswers(string answer1, string answer2, string answer3, string questionId1, string questionId2, string questionId3, string step, string userName, string selectedUserType)
{
...
ViewBag.step = responseStep;
ViewBag.showUsernameErrorMessage = responseShowUsernameErrorMessage;
ViewBag.userName = userName;
ViewBag.userType = selectedUserType;
return View("~/Views/Account/RecoverPassword.cshtml");
}

Related

Multiple Checkbox with Model returns null

after I read data from my database, I try to show those datas in Html.Helper checkbox and I do that. But later when I try to get checked values back to the controller, model always returns null. Here's my controller part:
[HttpGet]
public ActionResult NewClient()
{
HizmetModel hizmetModel = new HizmetModel();
hizmetModel.hizmet = db.Hizmet.ToList<Hizmet>();
return View(hizmetModel);
}
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, HizmetModel hizmet)
{
Musteri musteri = new Musteri();
if (!db.Musteri.Where(x => x.plaka == plate).Any())
{
musteri.isim = name;
musteri.soyisim = lastname;
musteri.telefon = telephone;
musteri.plaka = plate;
db.Musteri.Add(musteri);
db.SaveChanges();
}
Islem islem = new Islem();
IslemHizmet islemhizmet = new IslemHizmet();
islem.giristarihi = DateTime.Now;
islem.plaka = plate;
var selectedHizmet = hizmet.hizmet.Where(x => x.isChecked == true).ToList<Hizmet>();
db.Islem.Add(islem);
db.SaveChanges();
var onprocessplate = db.Islem.Where(x => x.plaka == plate).FirstOrDefault();
foreach (var item in selectedHizmet)
{
islemhizmet.islem_id = onprocessplate.islem_id;
islemhizmet.hizmet_id = item.hizmet_id;
db.IslemHizmet.Add(islemhizmet);
db.SaveChanges();
islemhizmet = new IslemHizmet();
}
TempData["Success"] = "Müşteri başarıyla eklendi...";
return RedirectToAction("CurrentClients", "Admin");
}
This is my model for the list:
public class HizmetModel
{
public List<Hizmet> hizmet { get; set; }
}
I use this model in the cshtml file:
#model otoyikama.Models.Model.HizmetModel
And this is the loop for displaying checkboxes
#for (int i = 0; i < Model.hizmet.Count; i++)
{
<li>
<label>#Model.hizmet[i].hizmetisim</label>
#Html.CheckBoxFor(m => m.hizmet[i].isChecked)
#Html.HiddenFor(m => m.hizmet[i].hizmet_id)
#Html.HiddenFor(m => m.hizmet[i].hizmetisim)
</li>
}
I couldn't figure what's the problem here, my get action works fine, I can see all the data from database but I can't pass them back to controller.
As a first think , u need to create a object in your controller parameters such as like List<int> serviceIDs or List<Service> services so you can keep more data than one.
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="services" value="#item.ServiceID">
<input type="hidden" name="services" value="#item.ServiceName">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<Service> services)
{
}
when u do in that way, u will able to hold more services than to one and i think u can pass them the controller more easly.
when i face with that stuation, im taking those services ID's and calling them on the controller side like bellow;
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="serviceIDs" value="#item.ServiceID">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<int> serviceIDs)
{
List<Service> services= new List<Service>();
foreach(var item in serviceIDs)
{
var service=db.Service.Where(x => x.ServiceID == item).Any()
if(service.Count!=0)
{
services.Add(service);
}
}
}

Parameter passing in an MVC Controller

I have the following ActionResult in my controller
[HttpGetAttribute]
public ActionResult _UpdateAlertNote(int recordId)
{
DealActionUpdateAlertNoteViewModel vm = new DealActionUpdateAlertNoteViewModel();
dtDeal_v10_r1.Manager objMan = new dtDeal_v10_r1.Manager(ref mobjSecurity);
dtDeal_v10_r1.Deal objDeal = default(dtDeal_v10_r1.Deal);
objDeal = objMan.GetDealObject(recordId, true);
vm.Message = objDeal.AlertMessage;
vm.IsDefaultStyle = objDeal.Alert_UseDefaultStyle;
vm.BackgroundColor = objDeal.Alert_BackgroundColor;
vm.FontColor = objDeal.Alert_FontColor;
vm.DealId = recordId;
return PartialView(vm);
}
Also the following ActionResult
[HttpPost]
public ActionResult _UpdateAlertNote(DealActionUpdateAlertNoteViewModel vm)
{
dtDeal_v10_r1.Manager objMan = new dtDeal_v10_r1.Manager(ref mobjSecurity);
objMan.UpdateAlertMessage(vm.DealId, vm.Message, vm.IsDefaultStyle, vm.FontColor, vm.BackgroundColor);
return this.PartialView("_action", vm.DealId);
}
When I execute this code it the "DealId" comes up as 0 in the Post.
I checked the Get and the DealId is being stored in the vm.DealId but is not passed through to the Post method.
I am not sure why it isn't passing could someone help me out with this.
****EDIT json added***
DealerSocket.TakeAction.updateDealAlertNote = function () {
var controller = "/DealAction/_UpdateAlertNote?mDeal_ID=";
var formId = "_UpdateDealAlertNoteFormElement";
DealerSocket.TakeAction.PostActionAndRefresh(formId, controller);
};
When you are posting an HTML Form element to a POST action, you need to make sure the value you pass to the view is stored in a Form element.
In this case of yours you will need something like:
<input type="hidden" value="#vm.DealId" />
within the <form> tag that you are Posting to the action.
Only elements inside the <form> tag will be serialized and sent to the Action.

MVC, cannot return to the previous URL

I am working on some legacy code.
I have a form which I edit some data and when I click save, if successful I want to return to the previous form.
So my controller methods are;
public ActionResult Edit(int callDiaryId)
{
ViewBag.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
var callDiary = this.SCDCallDiaryRepository.Get(callDiaryId);
return this.View("Edit", new DiaryItemViewModel(callDiary));
}
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateOnlyIncomingValuesAttribute]
public ActionResult Edit(DiaryItemViewModel item, string previousUrl)
{
var callDiary = this.SCDCallDiaryRepository.Get(item.SCD_CallDiaryId);
callDiary.Comments = item.Comments;
callDiary.ContractId = item.ContractId;
var opStatus = this.SCDCallDiaryRepository.Update(callDiary);
if (opStatus.Status)
{
this.TempData["SuccessMessage"] = "Details updated successfully.".MessageTime();
return RedirectToAction(previousUrl);
}
this.TempData["ErrorMessage"] = "Details NOT updated.".MessageTime();
ViewBag.PreviousUrl = previousUrl;
return this.View(new DiaryItemViewModel(callDiary));
}
and the incoming value of previousUrl is
http://localhost:58384/LogDiary/Comments?companyId=11033
This works perfectly for my back button.
But after my RedirectToAction command is performed, the Bad Request error that I get is because the Url it is showing is;
http://localhost:58384/LogDiary/http%3a/localhost%3a58384/LogDiary/Comments%3fcompanyId%3d11033
How do I fix this?
I was able to do this in the Controller of my App to return the user to the previous page
public ActionResult ChangePassword()
{
var userId = this.User.Identity.GetUserId();
var viewModel = this._userService.ChangePasswordViewModelForUser(userId);
viewModel.PreviousPage = this.Request.UrlReferrer.AbsoluteUri;
return this.View(viewModel);
}
If I need to use it in a button
#Resource.Button_Cancel
I think I found the answer.
Instead of using RedirectToAction, I am now using Redirect.
You can return to the previous form by doing the below code
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateOnlyIncomingValuesAttribute]
public ActionResult Edit(DiaryItemViewModel item)
{
..your other code..
return View(item);
}
it will return to the Edit page along with the entered data
hope this helps

ASP.NET MVC Postbacks and HtmlHelper Controls is not reflecting Model Changes

I'm facing problems with a MVC5 Razor web application. I have an authentication page (cshtml) that has an Id and password helper controls:
#model NetInfinity.Middleware.VistaModelos.LoginVistaModelo
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>#Login.Acceso</h1>
<p>
#Html.TextBoxFor(c => c.Id, new { #placeholder = #Login.Usuario, autofocus = "", autocomplete = "off", maxlength = "15", size = "15" })
</p>
<p class="p1">
#Html.PasswordFor(c => c.Clave, new { #placeholder = #Login.Contraseña, maxlength = "20", size = "20" })
#Html.ActionLink(".", "Cambiopwd", null, new { #class = "login-cambiarpwd", id = "Cambiopwd" })
</p>
<p class="login-recordarpwd">#Html.ActionLink(#Login.RecordarPwd, "Recordatoriopwd")</p>
<button type="button" class="login-submit" id="login-submit">#Login.LoginSubmit</button>
}
And the respective Model:
public class LoginVistaModelo
{
public string Id
{
get;
set;
}
[DataType(DataType.Password)]
public string Clave
{
get;
set;
}
public string MensajeError
{
get;
set;
}
}
And Controller Action that validates user is:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginVistaModelo vmUsuario)
{
if (ModelState.IsValid)
{
EntidadesBD backend;
var cache = MemoryCache.Default;
backend = (EntidadesBD)cache.Get("backend");
if (backend == null)
{
backend = new EntidadesBD();
var politica = new CacheItemPolicy { Priority = CacheItemPriority.NotRemovable };
cache.Set("backend", backend, politica);
}
Usuario usuario = vmUsuario.ValidaUsuario();
if (usuario == null)
{
vmUsuario.MensajeError = "error2";
vmUsuario.Id = vmUsuario.Clave = String.Empty; // <--- This not works
ModelState.Clear(); // <-- This not works
}
else
{
}
}
return View(vmUsuario);
}
When Login Action is triggered to validate user and password and error is thrown, I need to clear TextBoxFor value and PasswordFor value, and to achieve this I set model properties Id and Clave to string.empty in Controller, however when page (cshtml) is rendered again, controls keep old values ignoring model changes, not even if ModelState.Clear(). I've heard that HtmlHelpers controls (like .TextBoxFor() etc.) don't bind to model values on Postback, but rather get their value directly out of the POST buffer from ModelState. Please, ¿How can I do to update controls value when they are changed in Model properties?
Thanks
try making the value of model null before returning it to view,
like vmUsuario.id = null, vmUsuario.clave= null ; and thn return the empty model to view
A better approach for this type of problem would be to redirect the user, rather than returning the view. Otherwise you run into the problem that if they press F5 it reposts the data. So simply redirect the user, and use TempData to include your error message. In your Get method, check if TempData contains an error message and display it if it does.

Passing viewmodel from one method to another (post)

I have a wizardtype form where i would like to keep the model from the first step to the last.
This is how im doing it now, but i cant seem to keep the model from step 3 to 4.
[HttpPost]
public ActionResult Register(MemberViewModel model)
{
var mobile = model.Mobile;
var xml = MemberclubHelper.CreateVerificationTokenXML(mobile, "47");
MemberclubHelper.SendVerificationToken(xml);
return RedirectToAction("RegisterStep1", new { mobile = mobile });
}
public ActionResult RegisterStep1(string mobile)
{
var model = new MemberViewModel();
model.Mobile = mobile;
return View("Register/Step1", model);
}
[HttpPost]
public ActionResult RegisterStep1(MemberViewModel model)
{
var interests = (from interest in model.Interests where interest.isChecked select interest.value).ToList();
var passing = (from pass in model.Passing where pass.isChecked select pass.value).ToList();
var xml = MemberclubHelper.CreateMemberProfileXML(model.Mobile, model.FirstName, model.FirstName,
model.Email1, model.Zipcode, model.SelectedKid1, model.SelectedKid2, model.SelectedKid3,
model.Gender.ToString(), interests, passing);
model.XmlToSend = xml;
if (xml.Contains("error"))
{
model.ErrorMessage = xml;
return View("Register/Step1", model);
}
return View("Register/Step2", model);
}
[HttpPost]
public ActionResult RegisterStep2(MemberViewModel model)
{
var result = MemberclubHelper.SendCreateUser(model.XmlToSend, model.Password);
if (result.Contains("error"))
{
model.ErrorMessage = result;
return View("Register/Step2", model);
}
else
{
return View("Register/Finished");
}
}
I think you may be better served by creating a separate view model for each step (i.e., MemberViewModelStep1). To me this seems like only some of your MemberViewModel properties will will be set in each step unless you carry a lot of that state between steps via hidden inputs or some other mechanism.
Alternatively, have you considered using JavaScript to build up that state between across your steps and then submitting a single post with your fully populated MemberViewModel?

Resources