Back button Functionality on Review Details page beore the Submit button - c#

I want to show a Review page after the user fill sout all the information but on the review page I need to have a "Back" button which should take the user back tot he previous page with the same state and all the changes that they have made. What is the best way of achieving this ? I coded the review page on a different view but then the back is clicked the state of the page with all the changes I lost.
I have tried trying to code the view in another view page

The best way is that you support the parameters in your View:
For example:
public class MyClass
{
public IEnumerable<string> MyProperty { get; set; }
}
And in the Controller:
public ActionResult Index()
{
// Create your model and set the values
var myModel = new MyClass
{
MyProperty = new List<string> { "First Value", "Second Value" }
};
// Return the model back to your view for access using #Model
return View(myModel);
}
You have to generate your own model for the form completion, and then pass all the objects (Ideally just one with many attributes) from the review page to the form filling page and vice-versa.

Related

Force Save Sitefinity Widget MVC Controller Property

I am making a Sitefinity Widget using an MVC Controller. The widget shows and all that, no problem there. What I would like to do is save data for the widget in JSON form in a hidden property. I know how to make the property hidden via an attribute but I want to know how to POST data to my controller and set a property on the controller which will be saved in sf_control_properties table. Normally controller properties only get saved here when editing a widget's properties and clicking save in Admin UI. My control will have two modes (User view and Admin view). I am not making a custom designer via the edit modal popup. I am showing the design view while in page design mode on the widget itself. I have a save button that will do a POST to the controller on the backend. I want it so set a property and then persist it to the sf_control_properties table like a normal edit->modal->Save would do. I know I could connect directly to SQL and write the value but is there a better way to force a Widget Property to save in an MVC Controller than SQL brute force? Here is an example of my controller setup.
[ControllerToolboxItem(Name = "MyWidget", Title = "My Widget", SectionName = "Dashboard")]
public class MyWidgetController : Controller
{
public string Title { get; set; }
public string CssClass { get; set; }
public string CustomData {get;set;} //JSON string data
public ActionResult Index()
{
var viewModel = this.CustomData.FromJson<MyWidgetViewModel>();
return View(ViewModel);
}
[HttpPost]
public ActionResult Save(MyWidgetModel model)
{
this.CustomData = model.ToJson();
}
}
So basically when I do an ajax post to this controller I want to set this.CustomData = postModel.ToJson() and persist it to the sf_control_properties table.
I am doing this to avoid making a custom Dynamic Module with my own table, etc. When control loads in normal user view I will convert the this.CustomData property to C# class and use it in my razor view....

Update view after form submit

In my MVC controller I have two action methods.
The first one is Index method:
public IActionResult Index()
{
return PopulateViewModel();
}
The "PopulateViewModel" Action Method is used for updating of the view model and then showing these updated values on the Index view.
public IActionResult PopulateViewModel()
{
ViewModel viewModel = new ViewModel()
{
//updating values in the view model
//the values are received when the form in the view is submitted
};
return View("Index", viewModel);
}
The problem that I have is that on my Index view the updated values are not shown immediately after submitting the form in the view. When I submit the form I must then once again refresh the page to see the updated values.
What could be the reason for such behavior and how can I correct that?
You misunderstand the conceptual notion. The index is supposed to represent the initial page state. Other actions within the controller will modify the output by rendering the page with the adjusted model. Or handling server side model binding, but the concept is fundamentally achieving the same result.
Your controller logic should be within the following constraints.
public class SampleController : Controller
{
public IActionResult Index() => new View("...", ...);
public IActionResult SubmitSample(string location)
{
var model = service.GetLabLocations(location);
return View("...", model);
}
}
The index is simulating a GET request, returning the initial page in the required state. The form portion, should POST data, outlined in the SubmitSample portion of the code. This will change the state of the page, but the server will need to render with those changes. So the page will load with the attached model, for you to display.
This would represent Razor more than likely on the server side.
#if(Model != null)
foreach(var sample in Model)
{
// Markup, with the data
}

ViewModel update - changing properties before saving

After trying around the whole day with model bindings, without results, i decided to ask here.
I have got an asp.net razor view where a user (aka Seller) can edit his user details. Furthermore the user should be able to change his password.
I made a ViewModel:
public class EditSellerViewModel
{
public Seller Seller { get; set; }
public ChangePasswordModel ChangePasswordModel { get; set; }
}
My view has two forms which result in two "Submit" buttons. In my action i check which button was clicked. If the "Passwords" form has been submitted, i want to set the new Password in the Seller entity (that actually works) and SaveChanges() which does not change anything in the database (and does not throw any exception). It simply does nothing.
Furthermore if the "Seller Detail" form was submitted, i want to save the sellers data. But TryUpdateModel is always false, even if i use the second parameter which enables the prefix for ViewModels.
[HttpPost]
public ActionResult EditUser(string btnSubmit, FormCollection formValues, EditSellerViewModel editSellerViewModel)
{
int uid = baseFunc.GetIdForUsername(User.Identity.Name);
var seller = bmDBCont.SellerSet.Single(s => s.Id == uid);
if (btnSubmit == "saveSellerPassword")
{
seller.Password = editSellerViewModel.ChangePasswordModel.NewPassword;
bmDBCont.ObjectStateManager.ChangeObjectState(seller, System.Data.EntityState.Modified);
bmDBCont.SaveChanges(); //<-- does nothing
}
if (TryUpdateModel(seller, "Seller")) //<-- never true
{
bmDBCont.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Titles = CommonListsProvider.GetTitles();
ViewBag.Countries = CommonListsProvider.GetCountries();
return View(editSellerViewModel);
}
Here some debug info screenshots:
formcollection with seller form submitted
formcollection with password form submitted
Please can anyone help me?
See the documentation about TryUpdateModel, its says "Updates the specified model instance using values from the controller's current value provider and a prefix."
The Prefix to use when looking up values in the value provider.
Try use TryUpdateModel(seller) simple method without the "prefix" parameter.
if(TryUpdateModel(seller))
http://msdn.microsoft.com/en-us/library/dd493137(v=vs.108).aspx

In MVC4, how to save multiple row edits at once?

Every example that I can find of an MVC4 app has the edit working on one row of data at a time. It displays all the rows of data with each row having an edit which takes you to another page and allows you to edit that one row.
What I would like to do is display all the data elements in rows and instead of having the user have to click EDIT on each row, all the rows' data points would already be in text boxes which the user can directly update. And there is just one SAVE on the page that would just save all the updates/edits at once.
How can I setup my MVC app to support that?
You can use an EditorTemplates for this. The below example shows the normal form posting example. You can ajaxify it if you need by using the serialize method and sending form values.
Assuming You need to Edit the List of Student Names for a course. So Let's create some viewmodels for that
public class Course
{
public int ID { set;get;}
public string CourseName { set;get;}
public List<Student> Students { set;get;}
public Course()
{
Students=new List<Student>();
}
}
public class Student
{
public int ID { set;get;}
public string FirstName { set;get;}
}
Now in your GET action method, you create an object of our view model, initialize the Students collection and send it to our strongly typed view.
public ActionResult StudentList()
{
Course courseVM=new Course();
courseVM.CourseName="Some course from your DB here";
//Hard coded for demo. You may replace this with DB data.
courseVM.Students.Add(new Student { ID=1, FirstName="Jon" });
courseVM.Students.Add(new Student { ID=2, FirstName="Scott" });
return View(courseVM);
}
Now Create a folder called EditorTemplates under Views/YourControllerName. Then create a new view under that called Student.cshtml with below content
#model Student
#{
Layout = null;
}
<tr>
<td>
#Html.HiddenFor(x => x.ID)
#Html.TextBoxFor(x => x.FirstName ) </td>
</tr>
Now in our main view (StudentList.cshtml), Use EditorTemplate HTML helper method to bring this view.
#model Course
<h2>#Model.CourseName</h2>
#using(Html.BeginForm())
{
<table>
#Html.EditorFor(x=>x.Students)
</table>
<input type="submit" id="btnSave" />
}
This will bring all the UI with each of your student name in a text box contained in a table row. Now when the form is posted, MVC model binding will have all text box value in the Students property of our viewmodel.
[HttpPost]
public ActionResult StudentList(Course model)
{
//check for model.Students collection for each student name.
//Save and redirect. (PRG pattern)
}
Ajaxified solution
If you want to Ajaxify this, you can listen for the submit button click, get the form and serialize it and send to the same post action method. Instead of redirecting after saving, you can return some JSON which indicates the status of the operation.
$(function(){
$("#btnSave").click(function(e){
e.preventDefault(); //prevent default form submit behaviour
$.post("#Url.Action("StudentList",YourcontrollerName")",
$(this).closest("form").serialize(),function(response){
//do something with the response from the action method
});
});
});
You just need to specify the right model, list of example, and send the ajax with have information on each row (element of the array), read it on the server side and update each element accordingly. For this goal you use Post request. Just pass the list of elements as a parameters into the controller and pass it using the ajax.
For example you controller could be defined as:
public ActionResult Update(List<MyEntity> list)
{
...
}
public class MyEntity
{
public string Name {get; set;}
public int Count {get; set;}
}
and JavaScript could be as:
var myList = new Array();
// fill the list up or do something with it.
$.ajax(
{
url: "/Update/",
type: "POST",
data: {list: myList}
}
);
And of course your "Save" button has click event handler that will call that functionality with the ajax call.
For your convenience you can consider using KnockoutJS or other MVVM frameworks to bind the data with the DOM on the client side.

Persist Data through multiple form POSTs

I was wondering what the best way to approach this problem in ASP.NET MVC would be. The following is a trivial example of what I'd like to be able to do:
I have a webpage with textbox and a submit button. When the submit button is pressed the I would like the contents to be displayed on the same webpage. When it is pressed again I would like what was already displayed from the first submission to be displayed as well as the new data that was just submitted.
I have tried saving this data to a model, but the model is wiped clean every time the form posts. How could I do this and keep the data from the post before the last one (and the post before that)?
If you want data to persist between requests, as a starting point I would use 'TempData'. The TempData property value is stored in session state and exists until it is read or until the Session expires.
Example ViewModel:
public class SomeClass
{
public string Something { get; set; }
public List<string> RetainedValues { get; set; }
}
Example Controller:
[HttpGet]
public ActionResult Index()
{
return View("Index");
}
[HttpPost]
public ActionResult Index(SomeClass postedValues)
{
// retrieve retained values
var retained = (List<string>) TempData["RetainedValues"] ?? new List<string>();
retained.Add(postedValues.Something);
// save for next post
TempData["RetainedValues"] = retained;
// setup viewmodel
var model = new SomeClass
{
RetainedValues = retained
};
return View("Index", model);
}
Example View (strongly typed):
<div>
#foreach(var item in Model.RetainedValues)
{
<div>#item</div>
}
</div>
#using(Html.BeginForm())
{
#Html.EditorFor(m=>m.Something)
<input type="submit"/>
}
Just put an hidden field for your model property then your previews value will be loaded on it and passed it back to the next post.
Ex.: #Html.HiddenFor(model => model.YourProperty)
So knowing that you could have two properties ex.: one named newValue and other called allValues.
the allValues you use it with an hidden field and your newValue you use to insert the new ones. So on post you just add the newValue to the allValues.
Something like that:
model.allValues += newValue;
--UPDATE
Or you can use session or tempdata as mentioned by #Jesse
For this case I would prefer to use hidden fields as it has a lower complexity and its data didnt need be secure as it will be shown to the user anyway.

Categories