how to store user input value in local variable(in view) in asp.net mvc 5? - asp.net-mvc

i want to declare a local variable in my razor html form (view) and want to store user input value in that local variable.And then want to use that variable in foreach loop .in mvc 5 i am new to asp.net.
#using (Html.BeginForm("AddQuestion", "admin", new { id = ViewBag.qf_id }, FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-group">
<label>Question Statement</label>
#Html.TextBoxFor(a => a.Ques.QuestionString, new { #class = "form-control" })
#Html.ValidationMessageFor(a => a.Ques.QuestionString)
</div>
<div class="form-group">
<label>No. of option you want to add for this question </label>
<div class="col-md-4">
#{var val = #Html.TextBoxFor(a => a.counter, new { #class = "form-control" }); }
</div>
</div>
foreach(var item in val)
{
#Html.TextBoxFor(a=>a.Ans.AnswerStatement)
}
<div>
<button class="btn btn-primary" type="submit">Add</button>
</div>
}

What you are trying to do won't work unless it gets adapted to 1 of 2 solutions:
1) The only way this works is if the use enters a value in the textbox, then posts back to the controller, and the controller inputs this variable into the model, which the view then re-renders, using the number in the model, with the desired number of entries. That's the web forms way and is inefficient.
2) Using JavaScript, when a user enters a number, JavaScript can either render the markup using a templating framework, or make a request to the server, get the individual data, and return a partial view as HTML.

Related

How do I display results for one Id on a partial View MVC5

I am trying to display reservations for the current logged in restaurant but I am getting the following error.
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[RestaurantApplication.Models.Restaurant]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[RestaurantApplication.Models.RestaurantReservationEvent]'.
Here is my controller
public ActionResult RestaurantReservationsPartialView()
{
string currentUserId = User.Identity.GetUserId();
var restaurantID = (from r in db.Restaurants
where r.OwnerId == currentUserId
select r).ToList();
ViewBag.RestaurantId = restaurantID;
return PartialView("_RestaurantReservations", restaurantID);
And this is the view Calling the PartialView
<div style="padding-top: 50px;">
#Html.Action("RestaurantReservationsPartialView")
</div>
Here is the Partial view which I want to display the list of reservations for the current logged in restaurant.
#if (ViewBag.numReservations > 0 && ViewBag.ReservationStatus == "Pending")
{
<center><p id="pendingReservations">Here are your pending reservations</p>
</center>
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4 col-sm-4 col-xs-6">
<div class="panel panel-primary">
<div class="panel-heading">
<center><h1 class="panel-title">#Html.DisplayFor(modelItem => item.BookersName)</h1></center>
</div>
<div class="panel-body">
<h3 style="font-size: 16px">Booking Description: #Html.DisplayFor(modelItem => item.BookingDesc) <br />
Number of people: #Html.DisplayFor(modelItem => item.BookingNumberOfPeople)</h3>
<h3 style="font-size: 15px">
<h>Booking Date: #Html.DisplayFor(modelItem => item.BookingDate) at</h>
<h>#Html.DisplayFor(modelItem => item.BookingStartTime)</h>
</h3>
</div>
<div class="panel-footer">
<center>#Html.ActionLink("Accept", "AcceptReservation", new { id = item.RestaurantReservationEventID }, new { #class = "btn btn-success btn-xs" }) #Html.ActionLink("Decline", "DeclineReservation", new { id = item.RestaurantReservationEventID }, new { #class = "btn btn-danger btn-xs" })</center>
</div>
</div>
</div>
}
}
First of all, you are not calling a partial view from your main view, but invoking an action method using Html.Action method which returns a partial view result.
Your RestaurantReservationsPartialView action method is passing a list of Restaurant objects to it's (partial) view. But from the error message , it looks like your partial view is strongly typed to a list of RestaurantReservationEvent objects. You are getting this model type mismatch error because you are passing a wrong type to the partial view.
The solution is to pass the correct type. Since you want to pass the reservation for a specific restaurant, You probably want to accept the restaurant id as a parameter of your action method, use that to get the reservation events and pass that to the view.
Something like this.
public ActionResult RestaurantReservationsPartialView(int id)
{
var events = db.RestaurantReservationEvents.Where(x=>x.RestaurantId==id).ToList();
return View(events);
}
Assuming RestaurantReservationEvents is a property on your DbContext of type DbSet<RestaurantReservationEvent>. Please update the linq expression which returns a list of Restaurant to match with your situation
Now make sure you are passing the restaurant id when calling the action method.
<div style="padding-top: 50px;">
#Html.Action("RestaurantReservationsPartialView",,new { id=3})
</div>
Here i hard coded the Id value to 3.You may replace it with a variable which has the real value.

Showing values from controller in view in asp.net mvc

I have a form, with different input fields, where user can enter their information.
Inside of the form, I have 2 buttons. When user clicks one button called 'Add address', I want to fill up a div with the address. And when user clicks other button called 'Preview', the form is validated and prepared for preview page.
Below is how 'My Adrress' button is defined in Index.cshtml
<button id ="address" class="btn btn-default" onclick="location.href='#Url.Action("populateAddress","Information")?addressID=2222'">
Add Address
</button>
So, when user clicks, Add Address, I want to fill up the address that I am retrieving from database in the div on Index.cshtml. Below is where I want to display the retrieved address:
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-3">
#Html.Label("Address", htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-6">
#ViewBag.FeedAddress //Here I want to display my retrieved address
</div>
</div>
So, on button click, I am calling my 'Information' controller method 'populateAddress' and passing the addressID parameter '2222' to it.
Below is how I am defining my 'populateAddress' method in my controller:
public void populateAddress(string addressID = null)
{
var addressDetail = db.Agency.Where(e => e.AddressCode == addressID).ToList();
string AddressRetrieved= "";
string StreetAddress, City, State, Zip = "";
foreach(var detail in addressDetail )
{
StreetAddress = detail.Address;
City = detail.City;
State = detail.State;
Zip = detail.Zip;
AddressRetrieved= StreetAddress + Environment.NewLine + City + ", " + State + " - " + Zip;
}
ViewBag.FeedAddress = AddressRetrieved
}
So, here, my ViewBag is getting filled with my retrieved address.
But, my issue is, after it gets filled with the address, instead of showing it on my Index.cshtml page in the div where I am retrieving back the value from ViewBag, my page is instead getting submitted and showing my validations.
I want that, once user fills up part of the form above 'Add Address' button and clicks 'Add Address' button, my address is retrieved from ViewBag, shown inside the div and user proceed filling up the rest of the form.
I am unable to get this kind of behavior.
Can anyone please help me to achieve that behavior or may be tell what I am missing. Thanks!
EDIT:
Please find Index.cshtml code. The page is long, so I am just adding required code:
// input fields for user
<div class="form-group">
<div class="col-md-2">
#Html.Label("Title", htmlAttributes: new { #class = "control-label" }) </div>
<div class="col-md-6">
#Html.EditorFor((e => e.Title), new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
//Add Address button
<button id ="address" class="btn btn-default" onclick="location.href='#Url.Action("populateAddress","Information")?addressID=2222'">
Add Address
</button>
//section to display retrieved address
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-3">
#Html.Label("Address", htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-6">
#ViewBag.FeedAddress //Here I want to display my retrieved address
</div>
</div>
// input fields for user
<div class="form-group">
<div class="col-md-2">
#Html.Label("Description", htmlAttributes: new { #class = "control-label" }) </div>
<div class="col-md-6">
#Html.EditorFor((e => e.Description), new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
//Preview Button
<div class="form-group">
<div class="col-md-offset-2 col-md-6">
<input type="submit" value="Preview" class="btn btn-default" />
</div>
</div>
In the controller (named mainController for this example):
public JsonResult GetAddress(int addressId)
{
// do whatever to get what you need
// the Address model will need to be JSON serialized
return JSON(Address);
}
In the javascript:
function GetAddress(addressId)
{
$.ajax({
type: "GET",
async: false,
url: "/main/GetAddress?addressId=" + addressId
contentType: "application/json",
context: this,
success: function (data) {
console.log(data);
// do stuff here
},
error: function (error) {
alert("error");
}
});
}
Important routing info:
The url is "/main/GetAddress/" which means it will route to the controller mainController (notice the 'main' part matches) and the function inside the controller is GetAddress. It is a "GET" request so using the url variable is fine.
This is the basic structure of how you do an ajax call with MVC.
Special note: In the controller method you return a JsonResult, NOT an ActionResult! Use ActionResult when you are trying to route through a View and have the Razor engine create the HTML markup. But if you are just returning JSON, use JsonResult.
EDIT:
In case you want to do a POST instead of a GET, here is what it would look like:
In the controller:
public JsonResult PostSomething(MyClass data)
{
// do something with the data -- class is MyClass
var result = ...... // whatever the result is, Null is ok I'd recommend some sort of "successful" reply
return JSON(result);
}
In the javascript:
function SubmitForm()
{
var formData;
// common to use jQuery to get data from form inputs
// use JSON.stringify to serialize the object
var data = JSON.stringify(formData);
// the ajax is almost the same, just add one data: field
$.ajax({
type: "POST",
url: "/main/PostSomething"
contentType: "application/json",
data: data, // the second 'data' is your local variable
success: function(data){
console.log(data);
},
error: function(error){
alert(error)
}
});
}
The 'asynch: false' and 'context: this' from the first example are actually not necessary in either (most of the time).
As with most of programming, there is more than one way to do it. These examples are just simple (but fairly standard) snippets to get you on the right track.

New value in HTML.DropDownListFor(...) not setting in Controller [Post] method?

Hopefully someone can see how to go about this, because I've tried everything I can think of. When the Create() View in my MVC5 application loads I first populate several [SelectList(...)]'s in my Controller (ex.):
ViewBag.Model_Id = new SelectList(db.DBT_MODELS.OrderBy(x => x.MODEL_DESCRIPTION), "MODEL_ID", "MODEL_DESCRIPTION");
I then on my Create() View use this [SelectList(...)] to Populate an Html.DropDownListFor(...):
<div class="form-group">
<span class="control-label col-md-2">Model:</span>
<div class="col-md-4">
#Html.DropDownListFor(model => model.MODEL_ID, (SelectList)ViewBag.Model_Id, htmlAttributes: new { #class = "form-control dropdown", #id = "selectModel" })
#Html.ValidationMessageFor(model => model.MODEL_ID, "", new { #class = "text-danger" })
</div>
<div class="col-md-2">
<div class="btn-group">
<button id="createNewModel" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createModelFormContainer" style="display:none">
<form action="/createNewModel">
<input type="text" id="textNewModel" name="model_description" placeholder="New Model" />
<input type="button" id="submitNewModel" value="Submit" />
<input type="button" id="cancelNewModel" value="Cancel" />
</form>
</div>
</div>
</div>
Simple enough, and this all works as expected. The problem lies in a bit of extended functionality I've tried to incorporate. My main class has several of these properties which are basically Foreign Key's in my DB. When a User goes in to Create/Edit() an entity in my main Model, I wanted to allow them to be able to add new entities to these foreign tables without needing to navigate away from the current View.
As such, I added (for each foreign property, using (Model) as an example) the code shown above and again directly below with a button to Show/Hide a small form for users to insert a new value and have it added to the DropDownList:
<div class="col-md-2">
<div class="btn-group">
<button id="createNewModel" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createModelFormContainer" style="display:none">
<form action="/createNewModel">
<input type="text" id="textNewModel" name="model_description" placeholder="New Model" />
<input type="button" id="submitNewModel" value="Submit" />
<input type="button" id="cancelNewModel" value="Cancel" />
</form>
</div>
</div>
My submitNewModel() click event below gets the user's inputted new value and then uses a JSON call to a Controller Method to add it in the Database Table. This new value (and new ID for it) are then returned, the form for the DropDownList is reset, and I set the DropDownList's current value as the newly added one:
$('#createNewModel').click(function () {
$('#createModelFormContainer').show();
})
$('#cancelNewModel').click(function () {
$('#createModelFormContainer').hide();
})
$('#submitNewModel').click(function () {
var form = $(this).closest('form');
var data = { description: document.getElementById('textNewModel').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewModel", "INV_ASSETS")',
data: data,
success: function (resp) {
if (resp.ModelExists)
{
alert("Model [" + resp.Text + "] already exists. Please select from the DropDown.");
} else {
$('#selectModel').append($('<option></option>').val(resp.MODEL_ID).text(resp.Text));
form[0].reset();
$('#createModelFormContainer').hide();
var count = $('#selectModel option').size();
$('#selectModel').prop('selectedIndex', count - 1);
$('#selectModel').val(resp.MODEL_ID);
//document.getElementById('selectModel').value = resp.MODEL_ID; - Shows dropdown as blank [ ] once executed.
}
},
error: function () {
alert("ERROR - Something went wrong adding new Model [" + resp.Text + "]!");
$('#createModelFormContainer').hide();
}
});
//reloadForNewEntity();
});
The createNewModel() method that is called in my Controller:
public JsonResult createNewModel(string description)
{
DBT_MODELS model = new DBT_MODELS()
{
// ID auto-set during save.
MODEL_DESCRIPTION = description.Trim(),
CREATED_DATE = DateTime.Now,
CREATED_BY = System.Environment.UserName
};
var duplicateModel = db.DBT_MODELS.FirstOrDefault(x => x.MODEL_DESCRIPTION.ToUpper() == model.MODEL_DESCRIPTION.ToUpper());
try
{
if (duplicateModel == null)
{
if (ModelState.IsValid)
{
db.DBT_MODELS.Add(model);
db.SaveChanges();
// Ensure the [model.ID] is properly set after having been saved to and auto-generated in the database.
model.MODEL_ID = db.DBT_MODELS.FirstOrDefault(x => x.MODEL_DESCRIPTION.ToUpper() == model.MODEL_DESCRIPTION.ToUpper()).MODEL_ID;
}
}
else
{
model = duplicateModel;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = model.MODEL_ID, Text = model.MODEL_DESCRIPTION, ModelExists = (duplicateModel != null) }, JsonRequestBehavior.AllowGet);
}
Visually speaking, everything works as intended up to this point. The problem is when I go to Save the main entity I am Creating/Editing.
Any value that was already in the Foreign Tables, and thus in the DropDownList when the View loads, saves just fine; but if I add a new Foreign Table value for these main entity properties (though visually added and the currently selected values for the individual DropDownLists) the [POST] method then executes with each foreign id value set as 0 (ex. MainClass.Model_ID = "0" vs expected MainClass.Model_ID = "625", MainClass.Type_ID = "0" vs expected MainClass.Type_ID = "17", MainClass.Location_ID = "0" vs expected MainClass.Location_ID = "82", etc.)
Basically if the value selected in the Html.DropDownListFor() is one of my newly added values, the POST controller method always renders the MainClass.*_ID value which the selected Html.DropDownListFor() value corresponds to as "0".
Can anyone point me to how to get this working? I have tried:
Changing how my JavaScript sets the value in the DropDownList after the the JSON call to my Controller Actions returns (ex): //document.getElementById('selectModel').value = resp.MODEL_ID; - Shows dropdown as blank [ ] once executed. vs $('#selectModel').val(resp.MODEL_ID); which visually renders the expected new value in the DropDownList.
On return from the Controller method, setting a new ViewBag variable and then hoping to reference the saved value in the POST method (did not work, the JavaScript rendered my #Viewbag.PostModelID = resp.ModelID as "= resp.ModelID" and threw many expected errors).
EDIT:
[Redacted for N/A]
EDIT2: Good to go. Thanks everyone for the suggestions!
The json data you are returning from your action method is in this format.
{
"ID": 24,
"Text": "IOS",
"ModelExists": false
}
But in your code, you are trying to access MODEL_ID property which does not exist in the resp object.
$('#selectModel').append($('<option></option>').val(resp.MODEL_ID).text(resp.Text));
Change your code to use ID property value
$('#selectModel').append($('<option></option>').val(resp.ID).text(resp.Text));
$('#selectModel').val(resp.ID);
In your controller where you create the new model.. your json object that you're returning is ID, Text, ModelExists, but in your javascript you're setting the val property of the new <option> to MODEL_ID.. these 2 need to match..
So change your javascript to be
.val(resp.ID)
or change the return value in your controller action to
return Json(new { MODEL_ID = model.MODEL_ID, Text = model.MODEL_DESCRIPTION
You're also referencing MODEL_ID here
$('#selectModel').val(resp.MODEL_ID);
so make sure if you don't change your controller action, you update this also

JQuery AJAX: Update ViewModel

I have a strongly-typed MVC view that includes a form with an editor that is bound to a view model:
#model ViewModels.CommentView
#using (Ajax.BeginForm("UpdateComments", new AjaxOptions { HttpMethod="POST" }))
{
<fieldset>
<legend>Metadata</legend>
<div>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Comment)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment)
#Html.ValidationMessageFor(model => model.Comment)
</div>
</div>
<p class="action clear">
<input type="submit" value="Save" />
</p>
</fieldset>
}
When the user clicks on an element in a different part of the view, a JQuery AJAX call retrieves data from the server and updates the control:
<script type="text/javascript">
$(".load-comments").focus(function () {
var Id = $("#Id").val();
var url = "#Url.Action("GetComment")/" + Id;
$.ajax({ url: url, success: DataRetrieved, type: 'POST', dataType: 'json' });
function DataRetrieved(data) {
if (data) {
$("#Comment").val(data.Comment);
}
};
});
</script>
This functionality works as expected: the control content is visually updated. However, the value of the underlying html element is not updated, and when I post the form back to the server, the view model is empty.
How do I set the form controls' value in the JQuery function so that they post back to the server?
How did you set the HTML? ASP.NET default ModelBinder looks for id that are equals object properties to build the model back in the server. Looks like your form HTML doesnot reflect the object. Inspect each element created by Html helper and create each control as the same after comment data comes from the request. Hopes its help you! You can create a custom ModelBinder to Bind your model back in the server, take a look here: Model Biding

Pass constant value and variable (input) text from View to Controller

I'm fairly new to ASP.NET MVC and still getting used to some of the concepts.
I understand that to pass the value of a text box in the View back to the Controller, I can use Html.BeginForm and give the text box the same name as the corresponding parameter in the Controller Action.
Here's my situation: I have 2 buttons. I want them to call the same Action in the Controller. I want them to both pass the value for the text box (i.e. the "searchText").
However, I want one of the buttons to pass "false" for the parameter isQuickJump and I want the other button to pass "true" for the parameter isQuickJump.
Here is my View:
#using (Html.BeginForm("SearchResults", "Search", FormMethod.Get)) {
<div id="logo" class="centered">
<a href="SearchResults">
<img alt="Search" src="../../Content/themes/base/images/Search.jpg" />
</a>
</div>
<div id="searchBox" class="centered">
#Html.TextBox("searchText", null, new { #class = "searchTextBox" })
</div>
<div id="buttons" class="centered">
<input type="submit" id="searchButton" value="Search" class="inputBtn" />
#Html.ActionLink("Quick Jump", "SearchResults", "Search", new { isQuickJump = true }, new { #class = "btn" })
</div>
}
Controller:
public ActionResult SearchResults(string searchText, int? page, int? size, bool? isQuickJump, GridSortOptions sort)
{
var items = GetSearchGrid(searchText, page, size, sort);
if (Request.IsAjaxRequest())
return PartialView("_SearchResultsGrid", items);
return View(items);
}
Any suggestions on how to do this?
I appreciate your help!
Just use 2 submit buttons with the same name and different value:
<div id="buttons" class="centered">
<button type="submit" name="isQuickJump" value="false">Search</button>
<button type="submit" name="isQuickJump" value="true">Quick Jump</button>
</div>
Depending on which button is clicked the corresponding value will be sent to the server for the isQuickJump parameter. And since both are submit buttons, they will also submit all other input fields data to the server (which was not the case with the anchor that you used as the second button).

Resources