I have a Model class which knows to return current image, next image and previous image.
I have a Controller with an Action for switching slides.
That Action is triggered by Ajax.BeginForm which have a buttons for previous slide and next slide.
What can I do in the Action to make the view change slide without a page refresh?
Here is what I came up with so far:
Controller:
public class SlideshowController : Controller
{
static SlideshowModel slideshowModel = new SlideshowModel();
//
// GET: /Slideshow/
public ActionResult Index()
{
return View(slideshowModel);
}
public ActionResult GetCurrentSlideImage()
{
var image = slideshowModel.CurrentSlideImage;
return File(image, "image/jpg");
}
[HttpPost]
public ActionResult SlideshowAction(SlideshowModel model, string buttonType)
{
if (buttonType == ">")
{
slideshowModel.IncrementSlideNumber();
}
if (buttonType == "<")
{
slideshowModel.DecrementSlideNumber();
}
return JavaScript("alert('what to return to update the image?')");
}
}
View:
#model PresentationWebServer.Models.SlideshowModel
#using (Ajax.BeginForm("SlideshowAction", new AjaxOptions { UpdateTargetId = "result" }))
{
<img src="#Url.Action("GetCurrentSlideImage") " id="result"/>
<br />
<input class="float-left" type="submit" value="<" name="buttonType" id="btn-prev" />
<input class="float-left" type="submit" value=">" name="buttonType" id="btn-next" />
}
Very basic action
public class SlideshowController : Controller
{
...
public ActionResult GetCurrentSlideImage()
{
return Json("newImagePath.jpg");
}
...
}
On the client side add a jQuery ajax call :
<script>
function changeImage() {
$.ajax({
url: 'Slideshow/GetCurrentSlideImage',
type: post,
contentType: 'application/json',
success: function(data) {
$("#imageIDToReplace").attr("src", data);
},
complete: complete
}
});
}
</script>
Code not tested, but should give you the right idea
Edit:
You can return the image as data using image id in a new Action like this:
public ActionResult Image(string id)
{
var dir = Server.MapPath("/Images");
var path = Path.Combine(dir, id + ".jpg");
return base.File(path, "image/jpeg");
}
taken from Can an ASP.NET MVC controller return an Image?
then you can replace the src in the image attribute with the Action address
like -
http://localhost/MyController/Image/MyImage
Related
i am creating a simple inventory control system using Asp.net Mvc Json.when i am tring to load the category data.category Data is not loaded to the Dropdown menu. code which i tried so far i attached below along with the screen shot image.
enter image description here
Form design
<div class="card-action">
<div class="form-group">
<label class="form-label">Category</label>
<select class="form-control" id="category" name="category"
placeholder="Category" required>
<option value="">Please Select</option>
</select>
</div>
</div>
Jquery
getCategory();
function getCategory() {
$.ajax({
type: 'GET',
url: '/product/Getcategory',
dataType: 'JSON',
success: function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
$('#category').append($("<option/>", {
value: data[i].id,
text: data[i].cat_name,
}));
}
},
error: function (xhr, status, error) {
alert(xhr.responseText);
}
});
}
Controller
public class ProductController : Controller
{
aspoEntities db = new aspoEntities();
// GET: /Product/
public ActionResult Index()
{
return View();
}
public ActionResult Getcategory()
{
using (aspoEntities db = new aspoEntities())
{
var category = db.categories.ToList();
return Json(new { data = category }, JsonRequestBehavior.AllowGet);
}
}
}
Change your controller to
public class ProductController : Controller
{
// GET: /Product/
public ActionResult Index()
{
return View();
}
public ActionResult Getcategory()
{
aspoEntities db = new aspoEntities()
var category = db.categories.ToList();
return Json(category, JsonRequestBehavior.AllowGet);
}
}
It seems your db context has been disposed before the json is being serialized.
Try to inject the db context to your controller and get rid of the using statement.
Or move your return statement outside the using block.
I am creating a web application where there are five steps.
Home Page1 Page 2 Review Confirmation.
In the url, it goes like localhost:22112/Home/Page1 Page 2 and so forth.
My problem is if someone copies localhost:22112/Home/Page2, then it skips everything
and jumps to page 2 directly. So, how can I stop that? I did the following but its not working properly.
Any suggestions would be really helpful.
In the controller
private bool IsFromIndexPage()
{
if (Session["IsFromIndex"] != null)
{
return true;
}
else
{
return false;
}
}
And for each page actionresult, I am writing it like this.
[HttpGet]
public ActionResult Page1()
{
if (!IsFromIndexPage())
{
return RedirectToAction("Index");
}
.....other methods..
}
[HttpPost]
public ActionResult Page1(Information model, string command)
{
if (!IsFromIndexPage())
{
return RedirectToAction("Index");
}
.....other methods..
}
[HttpGet]
public ActionResult Page2()
{
if (!IsFromIndexPage())
{
return RedirectToAction("Index");
}
.....other methods..
}
[HttpPost]
public ActionResult Page2(Information model, string command)
{
if (!IsFromIndexPage())
{
return RedirectToAction("Index");
}
.....other methods..
}
If you're using session to store the progress through the steps you should be checking your session variables to validate the request is for the given page otherwise redirect the user to the first/current completed page.
You can write a custom request handler for this to keep your session validation code separate your controller code
see this Question about how to implement the basic functionality to what you want to do
EDIT:
switch(currentStep){
case 1:
return Step1(model)
break;
case 2:
return Step2(model)
break;
default:
return new HttpNotFoundResult();
break;
}
Here is a bit different approach, on how to make a wizard with asp.net MVC using ajax.
Your url will be /Home/Wizard on every step. Since using the AjaxOnly attribute, it will not be possible to visit Step1, Step2 etc (see reference in the bottom for AjaxOnly)
Controller:
public ActionResult Wizard()
{
return View();
}
[AjaxOnly]
public ActionResult Step1()
{
return PartialView("Step1");
}
[AjaxOnly]
public PartialViewResult Step2(FormCollection coll)
{
Session["FullName"] = coll["FullName"]!= null ? coll["FullName"].ToString() : string.Empty;
return PartialView("Step2");
}
[AjaxOnly]
public PartialViewResult Confirm(FormCollection coll)
{
WizardModel model = new WizardModel() { Name = Session["FullName"].ToString(), Phone = coll["Phone"] != null ? coll["Phone"].ToString() : string.Empty };
return PartialView("Confirm", model);
}
Model for last step:
public class WizardModel
{
public string Phone { get; set; }
public string Name { get; set; }
}
Make sure you reference jquery.unobtrusive-ajax in your page/layout page
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Wizard.cshtml
#{
ViewBag.Title = "Wizard";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Wizard - Overview</h2>
#using (Ajax.BeginForm("Step1", new AjaxOptions { HttpMethod="Get", UpdateTargetId = "wizardcontainer" }))
{
<input type="submit" value="Start wizard" />
}
<div id="wizardcontainer"></div>
Step1.cshtml
<div>
<h2>Wizard - Step 1</h2>
<br />
#using(Ajax.BeginForm("Step2", new AjaxOptions { UpdateTargetId = "wizardcontainer" }))
{
#Html.Label("FullName")
#Html.TextBox("FullName")
<input type="submit" value="Next >>" />
}
</div>
Step2.cshtml
<div>
<h2>Wizard - Step 2</h2>
#using(Ajax.BeginForm("Confirm", new AjaxOptions { UpdateTargetId = "wizardcontainer" }))
{
#Html.Label("Phone")
#Html.TextBox("Phone")
#Ajax.ActionLink("<< Previous", "Step1", new AjaxOptions { UpdateTargetId = "wizardcontainer" })
<input type="submit" value="Next >>" />
}
</div>
Confirm.cshtml
#model MvcApplication2.Controllers.WizardModel
<div>
<h2>Wizard - Final Stage</h2>
Name: #Model.Name
<br />
Phone: #Model.Phone
#Ajax.ActionLink("<< Previous", "Step2", new AjaxOptions { UpdateTargetId = "wizardcontainer" })
</div>
Look here for the AjaxOnly attribute:
http://helios.ca/2009/05/27/aspnet-mvc-action-filter-ajax-only-attribute/
I have a jquery function to check valid data on UsernameTextbox in my View. I want to prevent User click on the Register button until this field valid.
Disable button is it the best method? I just want when the value is not valid, user click on button just focus to the UsernameTextbox filed?
Update Code:
Here is my Model :
[Required]
[Remote("CheckUsername", "Account", ErrorMessage = "Username already exits.")]
public string Username { get; set; }
and Controller with GET method:
[HttpGet]
public JsonResult CheckUsername(string userName)
{
var user = IUserRepo.GetUserByUrName(userName);
bool isValid = true;
if (user!=null)
{
isValid = false;
}
return Json(isValid, JsonRequestBehavior.AllowGet);
}
and in my View :
#using (Ajax.BeginForm("Register","Account",new {area = "Area"},null))
{
#Html.ValidationSummary(true)
<table>
<tbody>
<tr>
<td class="info_label">Tên đăng nhập</td>
<td>#Html.EditorFor(m => m.User.Username)
</td>
<td class="check_user">#Html.ValidationMessageFor(m => m.User.Username)</td>
</tr>
<tr> ........
Why no error message appear? And i want to valid intermediately when user fill data or leave textbox like this site http://yame.vn/TaiKhoan/DangKy.
Note : The below mentioned suggestion is only for MVC3 and above
Luffy, you can remove the Ajax Call to check UserName existence
How can we do that ?
Model
public class UserModel
{
// Remote validation is new in MVC3. Although this will also generate AJAX
// call but, you don't need to explicitly type the code for Ajax call to
// check the User Existence. Remote Validation will take care of it.
[Required]
[Remote("CheckUsername", "Account", ErrorMessage = "User Already Exist")]
public string UserName { get; set; }
}
Controller
[HttpGet]
public JsonResult CheckUsername(string MyProp)
{
// Your Validation to check user goes here
bool isValid = true;
return Json(isValid, JsonRequestBehavior.AllowGet);
//Note - This will be called whenever you post the form.
//This function will execute on priority, after then the Index
//Post Action Method.
}
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(UserModel model)
{
// This action method will execute if the UserName does not exists
// in the DataBase
return View(model);
}
View
#using (Ajax.BeginForm("Action", "Controller", new { area = "Area" }, null))
{
#Html.TextBoxFor(i => i.UserName);
<input type="submit" name="Submit" value="Submit" />
// Whenever you submit the form, the control will go directly to
// CheckUsername function. In case the UserName doesn't exists only
// then the Post action method will be executed.
}
Scripts
<script src="jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="jquery.validate.min.js" type="text/javascript"></script>
<script src="jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
Try this
function CheckUserNameExits() {
$("#User_Username").on("blur", function () {
$("#User_Username").addClass("thinking");
var username = $("#User_Username").val();
if (username == "") {
$(".check_user").html("Ba?n chua nhâ?p tên dang nhâ?p.");
$("#User_Username").removeClass("thinking");
$("#User_Username").removeClass("approved");
$("#User_Username").addClass("denied");
$("#User_Username").focus();
$("#User_Username").select();
return false;
}
$.ajax({
url: "/Account/CheckUsername",
data: { userName: username },
dataType: "json",
type: "POST",
error: function () {
return false;
},
success: function (data) {
if (data) {
$("#User_Username").removeClass("thinking");
$("#User_Username").removeClass("denied");
$("#User_Username").addClass("approved");
$(".check_user").html("");
//$("#createuser").prop("disabled", false);
return true;
}
else {
$("#User_Username").removeClass("thinking");
$("#User_Username").removeClass("approved");
$("#User_Username").addClass("denied");
$(".check_user").html("Tên dang nhâ?p da~ duo?c du`ng, vui lo`ng cho?n tên kha´c.");
$("#User_Username").focus();
$("#User_Username").select();
//$("#createuser").prop("disabled", true);
return false;
}
}
});
});
}
function CheckValidate()
{
if (!CheckUserNameExits()){
return false;
}
return true;
}
<input id="createuser" type="submit" value="Ðang ky´ ta`i khoa?n" onclick="return CheckValidate();" />
May be it would be better to use jQuert enable/disable button method.
Fistly button is disable:
$(document).ready(function(){
$( ".register" ).button("disabled");
});
Than, if your function return true, enable button
function CheckUserNameExits() {
//*If your function is success
$( ".register" ).button( "enable" );
})
i have four different forms on my page and each are ajax forms.
I'm sending post request for first form with ajax to MVC Controller, it basically returns ViewData["TEST"] back to me.
I want to use ViewData on my view and i need set this to a hidden field for use other forms.
How i can reach it without using normal submit ?
Here is my code:
#using (Ajax.BeginForm("Index", new AjaxOptions{ HttpMethod = "POST" }))
{
<script type="text/javascript"> alert('#(ViewData["TEST"])'); </script>
<input type="text" name="name" />
<input type="button" onclick="javacript:SubmitAjax();" />
}
<script type="text/javascript">
function SubmitAjax() {
$.ajax({
type: 'POST',
data: $("#form0").serialize(),
url: "/Home/Index",
timeout: 2000,
async: false,
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(message_Error);
}
});
}
And Controller;
[HttpPost]
public ActionResult Index(string name)
{
ViewData["TEST"] = "TESTSTRING";
return View();
}
No ViewData !!!! . Simply return the content.
[HttpPost]
public ActionResult Index(string name)
{
return Content("TESTSTRING");
}
and to set this in the hidden field,you can do so int he success event of your ajax function
success: function (data) {
$("#hiddenElementID").val(data);
},
Also do not hard code the Path to action method like that. Always make use of the HTML helper methods.
Replace
url: "/Home/Index"
with
url: "#Url.Action("Index","Home")"
I personally prefer to avoid the AjaxBeginForm method and would like to write some clean handwritten javascript code to handle this.
#using(Html.Beginform())
{
<input type="text" name="name" />
<input type="submit" id="saveName" value="Save" />
}
<script type="text/javascript">
$(function(){
$("#saveName").click(function(e){
e.preventDefault();
$.post("#Url.Action("Index","Home")",
$(this).closest("form").serialize(),
function(data){
$("#yourHiddenElementID").val(data);
});
});
});
</script>
EDIT : As per the comment.
If you want to return multiple items, You can return JSON
Ex 2 : returning anonymous type to JSON
[HttpPost]
public ActionResult Index(string name)
{
return JSON(new { status : "true", ItemCount=35, UserName="Marc"} );
}
Ex 1 : returning a ViewModel to JSON
Assuming you have a class like
public class Result
{
public string Status { set;get;}
public int ItemCount { set;get;}
public string UserName { set;get;}
}
Now you can use this class and return it as JSON
[HttpPost]
public ActionResult Index(string name)
{
return JSON(new Result { Status : "true",
ItemCount=25, UserName="Scott"} );
}
I am using three partialview on a single view, I have a submit button on clicking of which I want to send information to database, I have to retrieve data from all the partialview.
Can You please provide me correct information to do it.
Darin I m using L2S so when I drag my stored procedure, I get code some thing like this in
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="SP_Name")]
public int SP_Name(
[global::System.Data.Linq.Mapping.ParameterAttribute(Name="EmployeeID", DbType="Int")] System.Nullable<int> EmployeeID
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), EmployeeID);
encounterID = ((System.Nullable<int>)(result.GetParameterValue(293)));
return ((int)(result.ReturnValue));
}
}
Updated
<script language="javascript" type="text/javascript">
$(function () {
$('#Form1').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (data) {
var message = data.Result;
$('#Result').html(message);
}
});
return false;
});
});
</script>
In my Controller I am using
public ActionResult Index(FormCollection frm)
{
My Code ---------------------
return Json(new { Result = "Success" });
}
When I return this I m getting a file in post back and it ask me to save it.
I have checked using flidder, in URL it shows me that the path as / only
where as If I fill any particular partialview It shows something like /Controller Name/Partialview
Can You help me with this problem
Well, sending data to a controller action is usually done by performing an HTTP request to this controller action. There are different ways of performing an HTTP request:
Use a <form> tag pointing to this action
Use AJAX
So if you go with the first approach you could have a single <form> wrapping all the partials which would have multiple submit buttons (with different names). Then when you click on one submit buttons all the input fields will be sent to the controller action and then inside the controller action you could process the data based on which submit button was clicked.
If you use the second option, well, then simply harvest the values you need to be sent uipon button click and send them along the AJAX request.
UPDATE:
As requested in the comments section here's how the first technique could be put into action. It uses two partials instead of three but it could be easily extrapolated.
As always you start by defining a view model which will represent the data you would like to work with on this particular view:
public class MyViewModel
{
public Partial1ViewModel Model1 { get; set; }
public Partial2ViewModel Model2 { get; set; }
}
public class Partial1ViewModel
{
public string Foo { get; set; }
}
public class Partial2ViewModel
{
public string Bar { get; set; }
}
Then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Model1 = new Partial1ViewModel { Foo = "foo" },
Model2 = new Partial2ViewModel { Bar = "bar" },
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// Here you have access to model.Model1.Foo and model.Model2.Bar =>
var button = "";
if (!string.IsNullOrEmpty(Request["submit1"]))
{
// submit1 button was used
button = "submit1";
}
else if (!string.IsNullOrEmpty(Request["submit2"]))
{
// submit2 button was used
button = "submit2";
}
var result = string.Format("thanks for submitting using {0}", button);
return Content(result, "text/plain");
}
}
and then a main view (~/Views/Home/Index.cshtml):
#model MyViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Model1)
#Html.EditorFor(x => x.Model2)
}
and the two corresponding editor templates (or partials if you will):
~/Views/Home/EditorTemplates/Partial1ViewModel.cshtml:
#model Partial1ViewModel
<h2>Partial 1</h2>
<div>
#Html.LabelFor(x => x.Foo)
#Html.EditorFor(x => x.Foo)
<input type="submit" value="Submit me!" name="submit1" />
</div>
~/Views/Home/EditorTemplates/Partial2ViewModel.cshtml:
#model Partial2ViewModel
<h2>Partial 2</h2>
<div>
#Html.LabelFor(x => x.Bar)
#Html.EditorFor(x => x.Bar)
<input type="submit" value="Submit me!" name="submit2" />
</div>