I'm using BeginCollectionItem with MVC 5 for adding and removing rows whenever.
One issue I'm having is with the delete function, I followed an online tutorial
which specified using #divId:first which seems to indicate deleting the first row whenever. This is no good for me, and wouldn't make sense to an end user.
As I'm using BCI I want to delete these from the html DOM so they won't have database Ids.
How do I delete by the Id of the model, this apparently (I think I read somewhere) is automatically generated by BCI?
Delete Function in the main view
$('#deleterow').live('click', function () {
$(this).parents('#newRow:first').remove();
return false;
});
Partial View with rows I want to delete by Id
#model Mvc.Models.Project
#using (Html.BeginCollectionItem("something"))
{
<div id="newRow">
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Update 2
When viewing the rendered html the data-action attribute renders as 0 for all objects so the JQuery can't and won't delete a row/object from the view.
Update
Instead of the check box I want to use the Delete link button, I assume this is possible? Not very familiar with jQuery but it is something I intend to look at, fairly new to MVC too but this is what I have so far:
Main View
<h3>Students</h3>
<div id="newStudent">
#foreach(var Student in Model.students)
{
Html.RenderPartial("_Student");
}
</div>
<input type="button" id="addStudent" name="addStudent" value="Add Student"/>
<input type="submit" value="Submit"/>
#section Scripts
{
<script type="text/javascript">
$('#addStudent').on('click', function () {
$.ajax({
async: false,
url: 'School/AddNewStudent'
}).success(function (partialView) {
$('#newStudent').append(partialView);
});
});
$('#newStudent').on('click', '.deleteStudent', function () {
var id = $(this).data('id');
if (id === 0) { // assumes Id is integer
$(this).closest('.studentRow').remove();
}
else { // existing item - controller to delete from Db
var url = '#Url.Action("action", "controller")';
$.post(url, { ID: id }, function (response) {
if (response) {
$(this).closest('.studentRow').remove();
}
}).fail(function (response) {
// display error message
});
}
});
</script>
}
Partial View
#using (Html.BeginCollectionItem("students"))
{
<div id="studentRow">
#Html.HiddenFor(m => m.Id)
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Controller
public class SchoolController : Controller
{
// GET: School
public ActionResult Index()
{
var newSchool = new School();
return View(newSchool);
}
public ActionResult AddNewStudent()
{
var student = new Student();
return PartialView("_Student", student);
}
[HttpPost, ActionName("DeleteStudent")]
public ActionResult DeleteStudent(School school)
{
foreach(var student in school.students.Where(s => !s.isDeleted))
{
return View(school.students);
}
return View();
}
}
What I have done is created a IsDeleted Property in Model/ViewModel, Put it in the Row as a Hidden Field, And also have a delete button against each Row
using (Html.BeginCollectionItem("Contacts"))
{
<div class="row mt-10">
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.isDeleted, new { data_is_deleted = "false" })
.......Removed HTML
<div class="col-md-1">
<span class="glyphicon glyphicon-trash" data-action="removeItem" title="remove" style="cursor:pointer"></span>
</div>
Then add this jQuery a JavaScript file. (Note: Don't add this to the Row Partial View, I add it in the View that calls the Row Partial View)
You might have to edit this jQuery to match your HTML structure, The goal in this jQuery is to update the IsDeleted field to either true or false and then Disable the other Input fields
$(document).on('click', '*[data-action="removeItem"]', function(e){
e.stopPropagation();
var btn = $(this);
var row = btn.closest('.row');
var parent = btn.parent();
var checkBox = parent.siblings('*[data-is-deleted]');
var checkBoxVal = checkBox.val();
if(checkBoxVal == 'False' || checkBox.val() == 'false'){
checkBox.val('true');
row.find('input, textarea, select').attr('readonly', 'readonly');
} else {
checkBox.val('false');
row.find('input, textarea, select').attr("readonly", false);
}
checkBoxVal = checkBox.val();
});
This is what your view will look like:
When post Back to Controller:
foreach (var contact in contacts.Where(s => !s.isDeleted))
{
// New and Updated Items
}
foreach (var contact in myModel.Where(s => s.isDeleted && s.Id!= 0))
{
// Deleted Items
// You don't have to delete Items where Id == 0, Bcz they are not in the DB.
// Just some Item added to the View and then deleted without Save
}
Deleted Items will be disabled: Note: You can Hide them by editing the above jQuery
EDIT A:
Actual controller code is something like this:
[HttpPost]
public ActionResult SaveStudent(Student model){
// Save model items
// Then Save the List of Items like this:
foreach (var contact in model.myListItems.Where(s => !s.isDeleted))
{
// New and Updated Items
}
foreach (var contact in model.myListItems.Where(s => s.isDeleted && s.Id!= 0))
{
// Deleted Items
// You don't have to delete Items where Id == 0, Bcz they are not in the DB.
// Just some Item added to the View and then deleted without Save
}
}
Firstly .live() was depreciated in jquery-1.7 and removed in 1.9. Use .on() instead. Next your generating invalid html by generating duplicate id attributes for the 'delete' link, which also means you will only ever be able to delete the first item and you never be able to delete newly added items because you are not using event delegation. Note also the BeginCollectionItem does not _ automatically generate the models ID_. All it does is add a prefix to the property name which includes an indexer value based on a guid so that the items can be bound to a collection on post back.
The link in your partial partial needs a class name and should store the Id value so it can be easily accessed in the script.
#using (Html.BeginCollectionItem("students"))
{
<div id="studentRow">
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.isDeleted) // not sure what the point of the data- attribute is
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Then your script needs to be (note the id="newStudent" for the enclosing <div> is confusing since you foreach loop is generating the html for existing items)
$('#newStudent').on('click', '.deleteStudent', function() { // use event delegation
var id = $(this).data('id');
if (id == 0) { // assumes property Id is typeof int
// Its a new item so just remove from the DOM
$(this).closest('.studentRow').remove();
} else {
// Its an existing item so call controller to delete it from the database
var url = '#Url.Action(""DeleteStudent", "School")';
$.post(url, { ID: id }, function(response) {
if(response) {
// The student was successfully deleted
$(this).closest('.studentRow').remove();
}
}).fail(function (response) {
// Oops, something went wrong - display error message?
});
}
});
And the controller
[HttpPost]
public JsonResult DeleteStudent(int ID)
{
// delete the student from the database based on the ID and signal success
return Json(true);
}
Related
I have a sort of Master-Detail Edit form and I'm trying to follow this post: Using Ajax... to get the partial view to postback.
My Edit form has a partial view that has a list of sub items, and another partial create view in it to add new items. I'd like the partial create view to post back and update the list without refreshing the whole page if possible.
Here's what I have so far:
MyController.cs -
public ActionResult Edit(int? id)
{
//...
ViewBag.CustomFormId = id;
using (var _db = new MkpContext())
{
//...
return View(profileEdit);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomForm editForm)
{
//...
if (!ModelState.IsValid) return View(editForm);
using (var _db = new MkpContext())
{
var form = _db.CustomForms.Find(editForm.CustomFormId);
//...
_db.Entry(form).State = EntityState.Modified;
_db.SaveChanges(User.ProfileId);
return RedirectToAction("Index");
}
}
public ActionResult _CustomFieldList(int id)
{
ViewBag.CustomFormId = id;
using (var _db = new MkpContext())
{
var formCustomFields = (from cf in _db.CustomFields
where cf.CustomFormId == id
select cf);
return PartialView(formCustomFields.ToList());
}
}
// Nested in _CustomFieldList
public ActionResult _CustomFieldCreate(int id)
{
var newField = new CustomField
{
CustomFormId = id
};
return PartialView(newField);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _CustomFieldCreate(CustomField addField)
{
ViewBag.CustomFormId = addField.CustomFormId;
if (ModelState.IsValid)
{
using (var _db = new MkpContext())
{
_db.CustomFields.Add(addField);
_db.SaveChanges();
}
var newField = new CustomField
{
CustomFormId = addField.CustomFormId
};
return PartialView(newField); // Probably need to change this somehow
}
return PartialView(addField);
}
And the views:
Edit.cshtml -
#model PublicationSystem.Model.CustomForm
#{
ViewBag.Title = "Edit Custom Form";
Layout = "~/Views/Shared/_LayoutSmBanner.cshtml";
}
<div class="form-horizontal">
<div class="row">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#* Fields for this form *#
}
<div id="CustomFields" class="col-md-6">
#Html.Action("_CustomFieldCreate", new { id = ViewBag.CustomFormId })
</div>
</div>
</div>
<script>
$(function () {
$("#createFieldForm").on("submit", function (e) {
e.preventDefault(); //This prevent the regular form submit
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
$("#CustomFields").html(result);
}
});
return false;
});
});
</script>
_CustomFieldCreate.cshtml -
#model PublicationSystem.Model.CustomField
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div id="result"></div>
<div class="form-horizontal">
<h4>CustomField</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model =>model.CustomFormId)
<div class="row">
#* Fields for the form *#
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div id="customFieldList">
#Html.Action("_CustomFieldList", new { id = ViewBag.CustomFormId })
</div>
_CustomFieldList.cshtml
#model System.Collections.Generic.IEnumerable<PublicationSystem.Model.CustomField>
<table class="table">
#* List table code *#
</table>
Edit: I rewrote the pages so that the list is part of the create partial view. What happens now is, if you enter data for _CustomFieldCreate and press submit, the first time, it refreshes just that view (including the nested list view). However the second time, it redirects to the view, probably because the first refresh didn't rebind the javascript to the submit button. Also, the Create view doesn't clear out the fields, but persists the originally entered data.
You will need a form in your partial view whose submit action binds to a javascript function that posts to your controller.
For example if your form id is MyForm:
$('#MyForm').on('submit', function (e) {
e.preventDefault(); //This prevent the regular form submit
$.ajax({
url: $(this).action, // This will submit the post to whatever action your form goes to
type: "POST", // This tells it that it is a post
data: $(this).serialize(), // This sends the data in the form to the controller
success: function (data) {
// do some javascript on success
},
error: function (xhr, ajaxOptions, thrownError) {
// do some javascript on error
}
});
});
This javascript overrides the default form submit and does an ajax post to your controller and then returns with success or error where you can do anything you want.
Here is some jquery ajax documentation:
http://api.jquery.com/jquery.ajax/
You should look into using AJAX. That should accomplish what I think you are describing. You'll want to create a javascript function that handles the submit event on the form, then post the form data to some create action in your MVC app using AJAX. If you are using jQuery, the library makes it pretty simple.
http://api.jquery.com/jquery.ajax/
I'm trying to add an unspecified number of rows to my database. These rows are created dynamically by the user's request:
$(document).ready(function () {
$(document).on('click', '#dataTable .add', function () {
var row = $(this).closest('tr');
if ($('#dataTable .add').length <= 100) {
var clone = row.clone();
// Clear the values.
var tr = clone.closest('tr');
tr.find('input[type=text]').val('');
$(this).closest('tr').after(clone);
}
});
// Only delete row if there exists more than one.
$(document).on('click', '#dataTable .removeRow', function () {
if ($('#dataTable .add').length > 1) {
$(this).closest('tr').remove();
}
});
});
So far what I am using to try and achieve this is a list with a maximum value of 100 elements (which I'd prefer a different method than this, perhaps one with no upper limit but this will do in the meantime), and I pass this list that I've created to my View():
// GET: Questions/Create
public ActionResult Create(int questionnaireUID)
{
List<QUESTION> questions = new List<QUESTION>();
for (var i = 0; i < 100; i++)
{
questions.Add(new QUESTION { QuestionnaireUID = questionnaireUID, Question1 = "" });
}
return View(questions);
}
In my View() here is the pertinent code sample that I am using to populate the values of my list (I believe my problems lie here...):
<table id="dataTable" name="dataTable">
#if (Model != null && Model.Count() > 0)
{
<tr>
#Html.HiddenFor(model => model[i].QuestionnaireUID)
<td>
#Html.EditorFor(model => model[i].Question1, new { htmlAttributes = new { #type = "text", #name = "question", #class = "question_input" } })
#Html.ValidationMessageFor(model => model[i].Question1, "", new { #class = "text-danger" })
<input type="button" name="addRow[]" class="add" value="Add">
<input type="button" name="addRow[]" class="removeRow" value="Remove">
</td>
</tr>
i++;
}
</table>
When I try to save this created list to my database, using the code below:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "QuestionnaireUID, Question1")] List<QUESTION> questions)
{
if (ModelState.IsValid)
{
foreach (var question in questions)
{
db.QUESTIONS.Add(question);
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(questions);
}
I am only able to save the first element of the list. The size of my list is always one, regardless of if the user dynamically generated 10 list elements.
Furthermore, if the first element has an error (e.g. it is empty) this error message is printed to all elements in the table. So, this being said although my list is able to generate in the view multiple elements/rows, for my database only one row is actually meaningful/used--which is the first row. How can I fix this?
As far as I know, MVC doesn't provide a built-in solution for handling dynamic/variable length lists. There are a few custom solutions that involve creating helpers to handle posting dynamic list objects. Here is one that I have used many times in the past, and is completely compatible with both old and current versions of ASP MVC (the blog uses old MVC markup, so you will need to update it to the RAZOR code for MVC3+).
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
The key component of this is the helper class "BeginCollectionItem", which handles the indexing of your list in a way that MVC will accept as a post-action parameter. Hope this helps.
I am trying to add a remove/delete a dynamically created partial view.
This is my ADD script.
$("#btnAdd").on('click', function () {
$.ajax({
async: false,
url: '/Employees/Add'
}).success(function (partialView) {
$('#AddSchedule').append("<tbody>" + partialView + "</tbody>");
});
});
this is the add controller
public ActionResult Add()
{
var schedViewModel = new FacultySchedViewModel();
return PartialView("~/Views/Employees/_DynamicView.cshtml", schedViewModel);
}
this is the partial view _DynamicView.cshtml
#using(Html.BeginCollectionItem("New")){
<td>
#Html.ActionLink("Delete", "DeleteThis", "MyController", null)
</td>
<td>
#Html.EditorFor(model => #Model.Schedule, new { htmlAttributes = new { #class = "form-control" } })
</td> }
what i can't figure out are
how to get the ID generated by BeginItemCollection
use the ID in a remove script
action on the controller
EDIT
1. How to connect it to a button or a link for removing the row
Added the view on the the Main of the partial view
#for (int i = 0; i < #Model.New.Count(); i++)
{
#Html.EditorFor(model => #Model.New[i])
}
The BeginItemCollection add a Guid as an indexer to the controls name and id attributes. It has no relevance at all to identifying an item to delete. You need add include the value of the property that identifies the FacultySchedViewModel object. Assuming its int ID, then change the partial to include a button and add the ID as a data- attribute
#using(Html.BeginCollectionItem("New"))
{
<tr>
<td><button type="button" class="delete" data-id="#Model.ID">Delete</button></td>
<td>#Html.EditorFor(model => #Model.Schedule, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
}
Then your script would be
var url = '#Url.Action("Delete")'; // assumes its in the same controller
$('.delete').click(function() {
var id = $(this).data('id');
var row = $(this).closest('tr');
if (id) { // or if(id == 0) depending if your property is nullable
row.remove(); // the item never existed so no need to call the server
return;
}
$.post(url, { ID: id }, function(response) {
if(response) {
row.remove(); // OK, so remove the row
} else {
// Oops - display and error message?
}
});
});
and the controller
[HttpPost]
public JsonResult Delete(int ID)
{
// Delete the item in the database
return Json(true); // or if there is an error, return Json(null); to indicate failure
}
Side note:
$('#AddSchedule').append("<tbody>" + partialView + "</tbody>"); is
adding a new tbody element for each item. Instead the main view
should include the tbody element and give it the id so its
$('#AddSchedule').append(partialView); or use $('#AddSchedule
tbody')append(partialView);
Does the model your posting back really have a property named New
(as you indicate in the BeginItemCollection method)?
As per your html render, what I suggest to modify your partial view as
From
#Html.ActionLink("Delete", "DeleteThis", "MyController", null)
To
#Html.ActionLink("Delete", "DeleteThis", "MyController", new { hidefocus = "hidefocus" } ) //add custom properties for here, which you can grab at client side or give css here.
Now search the anchor link via jQuery: Find the element with a particular custom attribute
When you get id, you can go parent like $('#id').parent().parent().hide() or empty()
or
As second option, is on click of Delete button call the same controller , but with a parameter to identify delete, so while returning give the null will bind in ajax again with empty string.
Why does Html.ActionLink render "?Length=4"
http://forums.asp.net/t/1787278.aspx?Add+and+remove+partial+views
I want to display the price of the selected item in the textbox in the view. For example, a product selected from the DLL has a price of 10 € and it should be displayed in the view. Can someone help?
Controler
public ActionResult Edit(int id)
{
Product product = DB.Products.Find(id);
ViewBag.Formats = new SelectList(storeDB.Format, "FormatID", "FormatName", "Price");
ViewBag.Foo = "Some Value"; //test
return View(product);
}
View
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-field">
#Html.DropDownList("Formats", ViewBag.Formats as SelectList, new { id = "DDLFormatsID" })
#Html.Display("Price") //displays nothing
#Html.Display("Foo") //working properly
</div>
</fieldset>
}
Update:
The problem seems to be in the order of the parameters in the constructor of the SelectList. I changed this line and it worked as you expected, showing the prices.
ViewBag.Formats = new SelectList(storeDB.Format, "FormatID", "Price");
You can check for the use of each parameter in the constructor. The first is for the data, the second is the name of the property that will hold the data to be send on the post, the third is the name of the property to be displayed.
Answer to the updated question:
If you want to show some value depending on the value in the dropdown then you can do it using javascript. First You have to identify the control to put your value, I'll use a span but you can use a textbox, etc. Then you subscribe to the change event of the dropdown and change the content of the first control every time.
Note that I'm using the value of the select to store the prices. If you want to receive the value as the id of the item you cannot use this approach. You need to store the prices in another place, you can use hidden elements.
You have to reference the jQuery library in the view.
The code is this:
public ActionResult Edit(int id)
{
Product product = DB.Products.Find(id);
ViewBag.Formats = new SelectList(storeDB.Format, "Price", "FormatName");
return View(product);
}
View
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-field">
#Html.DropDownList("Formats", ViewBag.Formats as SelectList, new { id = "DDLFormatsID" })
<span id="priceHolder"></span>
</div>
</fieldset>
}
<script src="~/Scripts/jquery-1.9.1.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#Formats").change(function () {
var $this = $(this);
var selectedValue = $this.val();
$('#priceHolder').html(selectedValue);
});
});
</script>
Hey guys so atm when the user goes to the holiday page, they can do 1 of 2 things
1)use a drop down box to select 'person name' and click 'view' this will display all the current holidays for this person
2)click 'create new' which will bring the user to a create page which allows them to add a new holiday(from here they select person name from drop and and select what date from calender)
This all works, however if the user originally follows the first path of selecting a person name and clicking view(it will display their holidays) if they then take the path of 2 and click 'create' it will jump to the create page. however the drop down box will be back at 'select' i would like the existing person selected from the previous drop down to display in this drop down.
A cookie or url/parameter?
anyway Im stuck please help
I've tried a cookie.
[code]
[HttpGet]
public ViewResult Index(string sortOrder, int? currentPersonID)
{
var holidays = db.Holidays.Include("Person");
HolidayList model = new HolidayList();
if (currentPersonID.HasValue)
{
model.currentPersonID = currentPersonID.Value;
}
else
{
model.currentPersonID = 0;
}
model.PList4DD = db.People.ToList();
//hyperlink to sort dates in ascending order
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "date" : "";
var dates = from d in db.Holidays
where d.PersonId == currentPersonID.Value
select d;
switch (sortOrder)
{
case "date":
dates = dates.OrderBy(p => p.HolidayDate);
break;
}
model.HList4DD = dates.ToList();
var cookie = new HttpCookie("cookie_name", "currentPersonID");
Response.AppendCookie(cookie);
return View(model);
}
public ActionResult Create()
{
var cookie = Request.Cookies["cookie_name"];
if (cookie != null)
{
string value = cookie.Value;
//int? value = cookie.Value;
}
ViewBag.cookie = cookie.Value;
ViewBag.Id = new SelectList(db.People, "Id", "Name");
return View();
}
//tried to use the currentPersonID in index as an int but it woudlnt allow me.
[/code]
My View
[code]
#model HolidayBookingApp.Models.startANDend
#{
ViewBag.Title = "Create";
}
<p>
<span>#ViewBag.cookie</span>
<h2>Create</h2>
<form action ="ListHolidays" id="listHolidays" method="post">
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Holiday</legend>
<div>
#Html.LabelFor(model => model.PersonId, "Person")
</div>
<div>
#Html.DropDownListFor(model => model.PersonId,
new SelectList(ViewBag.Id, "Value", "Text"),
"---Select---"
)
#Html.ValidationMessageFor(model => model.PersonId)
</div>
<div>
#Html.LabelFor(model => model.HolidayDate)
</div>
<div>
#Html.TextBoxFor(model => model.HolidayDate)
#Html.TextBoxFor(model => model.endDate)
<script>
// Date.format = 'dd/m/yyy';
$("#HolidayDate").addClass('date-pick');
$("#endDate").addClass('date-pick');
//$('.date-pick').datePicker//({dateFormat: 'dd-mm-yy'}).val();
// clickInput: true
$(function () {
//3 methods below dont allow user to select weekends
$('.date-pick').datePicker(
{
createButton: false,
renderCallback: function ($td, thisDate, month, year) {
if (thisDate.isWeekend()) {
$td.addClass('weekend');
$td.addClass('disabled');
}
}
}
)
.bind('click',
function () {
$(this).dpDisplay();
this.blur();
return false;
}
)
.bind('dateSelected',
function (e, selectedDate, $td) {
console.log('You selected ' + selectedDate);
}
);
// HolidayDate is start date
$('#HolidayDate').bind('dpClosed',
function (e, selectedDates) {
var d = selectedDates[0];
if (d) {
d = new Date(d);
$('#endDate').dpSetStartDate(d.addDays(0).asString());
}
}
);
//end date is end date
$('#endDate').bind('dpClosed',
function (e, selectedDates) {
var d = selectedDates[0];
if (d) {
d = new Date(d);
$('#HolidayDate').dpSetEndDate(d.addDays(0).asString());
}
}
);
});
</script>
#Html.ValidationMessageFor(model => model.HolidayDate)
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#*
<p>Current Person Selected is:
#TempData["currentPersonID"]
</p>*#
[code]
Once I get this going how can i get my drop down to store the value?
Any help?
Thanks
try to use the helper SelectList and pass to view a Model with a list of item and the id of the selected item.
#Html.DropDownList("name", new SelectList(Model.SomeList, "ItemValueId", "ItemDescription", Model.ItemValueId), new { #class = "someclass" })
To me, a cookie is a way of storing information across many different page and also if the user returns back after some time.
I would prefer using query string as the information needs to be passes from one page to other page. You can use javascript or jquery on 'Create' button click event, look to see if dropdown has a value, put it in a query string and redirect.
And I would suggest reading below:
http://www.codeproject.com/Articles/43457/Session-Cookie-Query-String-Cache-Variables-Unifie