I have an Ajax button that whenever I click it, it shows a single record from the database (in my Controller I used .Take(1) )
Here is my view :
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script type="text/javascript" language="javascript">
function ClearResults() {
$("#current").empty();
}
</script>
<div class="row">
<div class="column">
<h2 class="header-text">CURRENT</h2>
<div class="current" id="current">
X000
</div>
</div>
</div>
<div class="row">
#Ajax.ActionLink(" ", "BtnNext", null, new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "current",
LoadingElementId = "loading",
OnBegin = "ClearResults",
}, new { #class = "Middle-next dim btn btn-large-dim", #id = "Link1"})
</div>
Here is my controller for the button :
public PartialViewResult BtnNext(int count = 0)
{
System.Threading.Thread.Sleep(1000);
var model = db.Queues.OrderBy(x => x.QueueNumber).Take(1);
return PartialView("_queuenumber", model);
}
What I would like to do here is - whenever I click the next button it will display the first record from the database, then when I click it again it will show the second record and so on..
(as of now it only show the first data from database)
I wonder if that is even possible and what kind of stuff should I use to do that?
You're going to want to track the current index client-side (JavaScript) or in the Model (Razor), then pass that into your controller method, incrementing the value with each call. From the server side you would do something like:
var model = db.Queues.OrderBy(x => x.QueueNumber).Skip(index).Take(1);
I'd recommend sending back a ViewModel. For the Razor implementation you could have a ViewModel that contains the displayed values, the Queue ID, and the index. I.e.
public class QueueViewModel
{
public int QueueId { get; set; }
public int QueueNumber { get; set; }
public string Name { get; set; }
// ..
public int NextIndex { get; set; }
}
public PartialViewResult BtnNext(int index = 0)
{
var model = db.Queues.OrderBy(x => x.QueueNumber)
.Select(x => new QueueViewModel
{
QueueId = x.QueueId,
QueueNumber = x.QueueNumber,
Name = x.Name,
NextIndex = index + 1
})
.Skip(index).Take(1);
return PartialView("_queuenumber", model);
}
Then in the view would be something like below: (Sorry, my Razor is pretty rusty)
#Ajax.ActionLink(" ", "BtnNext", "QueueController",
new { index = Model.nextIndex },
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "current",
LoadingElementId = "loading",
OnBegin = "ClearResults",
}, new { #class = "Middle-next dim btn btn-large-dim", #id = "Link1"})
This would need some verification for behaviour to ensure that the first call goes through with an index value of "0", but should hopefully give you some ideas to pursue.
Related
Goal: I'm setting up the checkout page for my website and would like to have the user select from a list of their addresses. When they select it, it will add it to the cache and save it for when they have everything set up and are ready to complete their order.
Issue: When selecting the address, and pressing save changes, it returns 0 instead of the actual value of the item and I don't know why.
Here's the form:
Here's the view:
#model AirmotionEcommerceWebsite.Models.Home.CheckoutModel
#{
ViewBag.Title = "Checkout";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<div class="container">
<h1>Checkout</h1>
<form>
<div class="jumbotron row product-container">
<div class="col-md-4">
#{
IEnumerable<SelectListItem> dataItems = ViewBag.UserAddresses;
}
<div class="form-group">
<h4>To Address:</h4>
#Html.DropDownListFor(model => model.selectedShippingAddress.IntShippingAddressId, dataItems, "-- Select --", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.selectedShippingAddress.IntShippingAddressId, "", new { #class = "text-danger" })
<a asp-controller="Home" asp-action="AddShippingAddress">Add New Address</a>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" data-ajax-method="get" data-toggle="ajax-modal" data-target="#ValidateAddress"
data-url="#Url.Action("CheckoutChanges", new { intShippingAddressID = Model.selectedShippingAddress.IntShippingAddressId })">Verify Address</button>
</div>
</div>
</div>
</form>
</div>
<script>
$(function () {
$('button[data-toggle="ajax-modal"]').click(function (event) {
event.preventDefault();
var url = $(this).data('url');
// get the form containing the submit button
var form = $(this).closest('form')
// serialize all the fields in the form
var model = form.serialize();
// the the request to the url along with the form (model) data
$.get(url, model).done(function (data) {
PlaceHolderElement.html(data);
})
})
})
</script>
Here's the controllers:
[Authorize]
public ActionResult Checkout()
{
// get userid
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
// get addresses for this user
ViewBag.UserAddresses = GetShippingAddresses(userId);
CheckoutModel model = new CheckoutModel();
model.selectedShippingAddress = new TwebShippingAddress();
bool AlreadyExists = memoryCache.TryGetValue<CheckoutModel>("CachedModel", out model);
if (!AlreadyExists)
{
model = new CheckoutModel();
model.selectedShippingAddress = new TwebShippingAddress();
var cachEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
memoryCache.Set("CachedModel", model, cachEntryOptions);
}
return View(model);
}
[HttpGet]
public ActionResult CheckoutChanges(int intShippingAddressID)
{
if (intShippingAddressID == 0)
return View();
CheckoutModel model = new CheckoutModel();
bool AlreadyExists = memoryCache.TryGetValue<CheckoutModel>("CachedModel", out model);
if (AlreadyExists)
{
model.selectedShippingAddress = context.TwebShippingAddresses.Where(x => x.IntShippingAddressId == model.selectedShippingAddress.IntShippingAddressId).FirstOrDefault();
var cachEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
memoryCache.Set("CachedModel", model, cachEntryOptions);
}
return View();
}
Lastly, this is the GetShippingAddresses() method:
public IEnumerable<SelectListItem> GetShippingAddresses(string strUserID)
{
List<SelectListItem> list = new List<SelectListItem>();
var cat = context.TwebShippingAddresses.Include(x => x.IntState).Where(x => x.IntWebUserId == strUserID).OrderByDescending(x=>x.BlnIsDefault);
foreach (var item in cat)
{
list.Add(new SelectListItem { Value = item.IntShippingAddressId.ToString(), Text = item.StrName + " " + item.StrAttnTo + " " + item.StrStreet1 + " " + item.StrStreet2 + ", " + item.StrCity + " " + item.IntState.StrStateCode + " " + item.StrZip });
}
return list;
}
Replace the $.get like this to pass a Json object that will be auto binded to the action's parameter:
<script>
$(function () {
$('button[data-toggle="ajax-modal"]').click(function (event) {
event.preventDefault();
var url = $(this).data('url');
// get the form containing the submit button
var form = $(this).closest('form')
// serialize all the fields in the form
var model = form.serialize();
// the the request to the url along with the form (model) data
int selectedIndex = //Write jquery code to get the selected index here
$.ajax({
type: 'GET',
url: url,
data: { intShippingAddressID: selectedIndex },
dataType: 'json',
})
.success(function( data ) {
PlaceHolderElement.html(data);
});
})
})
</script>
Note the Json data type and the property that match the parameter of the Action.
I am sort of lost on the coding part of this problem. I have a MVC application, and I am trying to populate a queries Where clause as the selected value from my drop down list. Also, I am populating the drop down list from a query in the database. For example:
SELECT db.ID FROM Database db where ID = 1232
Instead of that, I want to do something like this...
SELECT db.ID FROM Database db where ID = "SelectedValue from Dropdownlist"
Model Class:
public string ID {get; set;}
public string Summary{get; set;}
public int Estimate {get; set;}
public List<Hello> getIDs()
{
var que = (from wre in db.Table
select new Hello{
ID = wre.ID
}).toList();
}
Controller class:
public ActionResult Index(string? IDParam)
{
var model = test.getStuff();
var que = (from wre in db.View
where wre.ID == IDParam //Operator '==' cannot be applied to operands of type 'string' and 'string?'
select new Hello
{
ID = wre.ID
Summary = wre.Summary,
Estimate = wre.Estimate
}).toList();
if (IDParam!= null & IDParam.HasValue)
{
model = model.Where(x => x.ID == IDParam); //Operator '==' cannot be applied to operands of type 'string' and 'string?'
}
return View(model);
}
View Class:
#Html.DropDownList("ID", ViewBag.Releases as SelectList, "ID", new {#id="rel" })
<table>
<th>#Html.DisplayNameFor(model => model.ID)</th>
<th>#Html.DisplayNameFor(model => model.Summary)</th>
<th>#Html.DisplayNameFor(model => model.Estimate)</th>
</table>
<script>
$("#rel").change(function () {
var selectedId = this.val();
location.href = '#Url.Action("Index", "SampleController", new {selectedId="_selectedId"})'.Replace("_selectedId",selectedId);
});
</script>
This works perfectly fine, but now, I am lost on the coding aspect of it. I can see the alert every time I change the ID from the drop down list. However, there is no change in the data being displayed (I know I am missing a lot). If anyone can help me out here, that would be great, thank you!
1) Try adding where clause in Linq
where wre.ID == IDParam
2) Change que to instance of your class and get firstOrDefault instead of List
3) Try passing instance of your class as a model in view
return View(test);
1- You need to get changed Id as below :
$("#rel").change(function () {
// alert("Changed");
var selectedId =this.value;
});
2- If you want to reload your page then you need to set a parametre to your [HttpGet] Method :
public ActionResult Index(int? selectedId) // selectedId
{
var que = (from wre in db.View
select new Hello
{
ID = IDParam
Summary = wre.Summary,
Estimate = wre.Estimate
}).toList();
ViewBag.Releases = new SelectList(test.getIDs(), "", "ID");
var model = test.getStuff();
if(selectedId!=null && selectedId.HasValue)
{
// do some stuff with your selectedId
// if working method is test.getStuff(), then maybe you can use like code below:
model = model.Where(x=> x.Id==selectedId);
}
return View(model);
}
and in your View:
$("#rel").change(function () {
// alert("Changed");
var selectedId =this.value;
location.href = '#Url.Action("Index", "YourController", new {selectedId="_selectedId"})'.Replace("_selectedId",selectedId);
});
3- If you dont want to reload page then you need to use Ajaxrequest, You must create a new method for get data by selectedId,
// Your view.
$("#rel").change(function () {
// alert("Changed");
var selectedId =this.value;
$.ajax({
method: "POST",
url: "'#Url.Action("GetDataBySelectedId","YourController")'",
data: { selectedId: selectedId }
})
.done(function( data) {
// Delete your table, and fill table with your data with jquery.
});
});
// your Controller:
[HttpPost]
public JsonResult GetDataBySelectedId(int? selectedId)
{
// Do some stuff for get your data.
var data = yourData.Where(x=> x.Id = selectedId.Value);
return Json(data);
}
I have two tables one is country table another one is doctor table both contains country fields.if i select any country name from country based on the country name i want to display doctors name from the doctor table.
<div class="col-lg-4">
<fieldset class="form-group">
<label class="form-label" for="exampleInputEmail1">Country</label>
#Html.DropDownList("CountryID", null, "--- Select Country ---", new { #class = "select2-arrow" })
#Html.ValidationMessageFor(model => Model.CountryID, null, new { #style = "color: red" })
</fieldset>
</div>
<div class="col-lg-4">
<fieldset class="form-group">
<label class="form-label" for="exampleInput">Doctor Name</label>
<select id="UserRefID" class="select2-arrow"></select>
#Html.ValidationMessageFor(model => Model.UserRefID, null, new { #style = "color: red" })
</fieldset>
</div>
Country bind Code:
#region Country
public void Country_Bind()
{
userType type = new userType();
DataSet ds = type.Get_Country();
List<SelectListItem> coutrylist = new List<SelectListItem>();
foreach (DataRow dr in ds.Tables[0].Rows)
{
coutrylist.Add(new SelectListItem { Text = dr["CountryName"].ToString(), Value = dr["CountryID"].ToString() });
}
ViewBag.CountryID = coutrylist;
}
#endregion
DAL :
public DataSet Get_Country()
{
SqlCommand cmd = new SqlCommand("Select * From Country", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
Doctor Bind based one country ID
#region Doctor Bind
public JsonResult Company_Bind(string CountryID)
{
userType type = new userType();
DataSet ds = type.Get_Doctor(CountryID);
List<SelectListItem> Doctorlist = new List<SelectListItem>();
foreach (DataRow dr in ds.Tables[0].Rows)
{
Doctorlist.Add(new SelectListItem { Text = dr["Tittle"].ToString() + " " + dr["DoctorName"].ToString(), Value = dr["DoctorID"].ToString() });
}
return Json(Doctorlist, JsonRequestBehavior.AllowGet);
}
#endregion
public DataSet Get_Doctor(string CountryID)
{
SqlCommand com = new SqlCommand("Select * from DoctorRegistration where Country=#Country", con);
com.Parameters.AddWithValue("#Country", CountryID);
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
<script>
$(document).ready(function () {
$("#CountryID").change(function () {
var id = $(this).val();
$("#UserRefID").empty();
$.get("Company_Bind", { CountryID: id }, function (data) {
var v = "<option>--- Select State ---</option>";
$.each(data, function (i, v1) {
v += "<option value=" + v1.Value + ">" + v1.Text + "</option>";
});
$("#UserRefID").html(v);
});
});
});
</script>
If i use [Authorize] i cann't use ajax function
//[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
{
//
// GET: /Account/
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
public ActionResult Register()
{
UserType_Bind();
Country_Bind();
//Doctor_Bind();
return View();
}
if i don't use [Authorize] working fine
You are passing the string Company_Bind as the url for the ajax call. So it will be appended to the current pages url and a call will be made to that.
For example, if your currrent page is yourBaseUrl/Home/Index, the call will be made to yourBaseUrl/Home/index/Company_Bind?CountryID=4
If your current page is yourBaseUrl/Doctors/List, the call will be made to yourBaseUrl/Doctors/List/Company_Bind?CountryID=4
This will give you 404 response as that is invalid url to your action method.
You should consider using the Url.Action helper method to generate the correct relative path to the action method, irrespective of your current page.
So if your javascript code was inside a razor view,you can directly use it like
$.get("#Url.Action("Company_Bind")", { CountryID: id }, function (data) {
});
Or use the Url.Action overload which accepts the action method name and controller name.
$.get("#Url.Action("Company_Bind","Doctors")", { CountryID: id }, function (data) {
});
If it is in an external js file, you can still use the Url.Action helper in the razor view to generate the url and pass it to the external js file as explained in this post.
I know that a very similar question was posted and ansered:
How to gracefully handle AJAX PartialView update when Javascript is disabled
But that solution isnt satisfying me.
Is it possible, to update a Element with the Ajax Helper Method when Java Script is disabled, that it will show a partial view in the same page and not in an extra tab?
I want that the Tag in the Index View is updated with a partial View (_Details), when I click on a AJAX ActionLink.
With the PView 1 Method, I get the same result with JS enabled and disabled. But i dont linke the PView 1 solution (as suggested in the similar question), because this makes the Partial View Class useless. Why would i need it when i reload the hole page anyway.
I would prefer a solution similar to PView 2. But there the Partial View is opened in a new Tab when JS is disabled.
My very simplified code so far:
HomeController Class
public class HomeController : Controller
{
public ActionResult Index()
{
var obj_str = new SimpleString { astr = "Nothing Yet" };
return View(obj_str);
}
public ActionResult PView1()
{
string str_posted = "String of PView 1";
var obj_str = new SimpleString {astr = str_posted};
if (Request.IsAjaxRequest())
{
return PartialView("_Details", obj_str);
}else
{
return View("Index", obj_str);
}
}
public PartialViewResult PView2()
{
var obj_str = new SimpleString {astr = "String of PView 2"};
return PartialView("_Details", obj_str);
}
}
Index.cshtml
<h2>AJAX Actionlink Index</h2>
#Ajax.ActionLink("Click me for PView 1", "PView1", new AjaxOptions
{
UpdateTargetId = "partv",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
})
#Ajax.ActionLink("Click me for PView 2", "PView2", "Home", new AjaxOptions
{
UpdateTargetId = "partv",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
})
<h3>Partial View here!</h3>
<div id="partv">
<p>#Model.astr</p>
</div>
_Details.cshtml (the Partial View)
#model MVCPartialViewTest.Models.SimpleString
<p>This is from the Partial View cshtml</p>
<p>#Model.astr</p>
SimpleString Class (the Model)
public class SimpleString
{
public string astr { get; set; }
}
we are writing an ASP.NET MVC3 Application and want to do it "rich", for example by using bootstrap und modal dialogs.
I now wonder how to implement modal dialogs, without breaking all the cool staff from ASP.NET (ModelErrors, ...).
The workflow should be like this:
IndexView with a list of items, each item with an actionlink that shows a modal dialog
#Ajax.ActionLink(
"Edit", // Link Text
"Edit", // ActionMethod
new { id = item.Id }, // RouteValues
new AjaxOptions {
HttpMethod = "Get",
OnBegin = "modal.showModalDiv()",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "modal-div",
OnSuccess = "modal.ajaxSuccess()" },
new { data-toggle = "edit-modal" } // HTML-Attributes
)
The modal dialog (simple div styled with css) renders the editview (returned from controller actionmethode)
[HttpGet]
public ActionResult Edit(int id) {
// Load Data and create Model
var model = new ...
return PartialView(model);
}
The form in the edit view can be used to edit the item, including client-side validation
#{
AjaxOptions ajaxOptions = new AjaxOptions() {
HttpMethod = "Post", OnSuccess="modal.hideModalDiv()"
};
}
#using (Ajax.BeginForm("Edit"), ajaxOptions){
... element to edit item ...
<input type="submit" value="submit" />
}
When the submit edit controller-methode recognizes errors (not caught by client-side-validation) the page should be displayed again with model-errors. Otherwize the index-page should be shown or the table refreshed and the modal dialog closed.
[HttpPost]
public ActionResult Edit(Guid id, ItemModel model) {
try{
...Save Item ...
return RedirectToAction("Index")
} catch (Exception ex){
ModelState.AddModelError("", "An error occured")
return PartialView(model);
}
}
My Problem is: How to implement step 4? Does Someone has an advice?
Try with this,
[HttpPost]
public ActionResult Edit(Guid id, ItemModel model)
{
if(model != null && ModelState.IsValid)
{
return RedirectToAction("Index")
}
else
{
return PartialView(model);
}
}
I guess you've already solved this problem or found a work around but in case you have not I suspect if you were to return a partial view that contains javascript to do the redirection you could get the behaviour you describe.
For example:
RedirectToIndex.cshtml
#{ Layout = null; }
<script type="text/javascript">
window.location.href = "#Url.Action("Index")";
</script>
Then update your action to return this partial view.
[HttpPost]
public PartialViewResult Edit(Guid id, ItemModel model) {
try{
//Save Item ...
return PartialView("RedirectToIndex")
} catch (Exception ex){
ModelState.AddModelError("", "An error occured");
return PartialView(model);
}
}
Not the most graceful but should work, I say should as I have not tested this...