Controller AJAX method to return AJAX ActionLink - asp.net

I am fairly new to MVC and just trying to achieve something which I think shouldn't be too complicated to achieve. Just want to know what the best approach for that is. I have an Event-RSVP application (NerdDinner kind) where you go to view details of the event and then click on an AJAX link that will RSVP you for the event.
<%
if (Model.HasRSVP(Context.User.Identity.Name))
{
%>
<p>
You are registered for this event!
<%:
Ajax.ActionLink("Click here if you can't make it!", "CancelRegistration", "RSVP", new { id = Model.RSVPs.FirstOrDefault(r => r.AttendeeName.ToLower() == User.Identity.Name.ToLower()).RSVPID }, new AjaxOptions { UpdateTargetId = "QuickRegister"})
%>
</p>
<%
}
else
{
%>
<p>
<%:
Ajax.ActionLink("RSVP for this event", "Register", "RSVP", new { id=Model.EventID }, new AjaxOptions { UpdateTargetId="QuickRegister" }) %>
</p>
<%
}
%>
Now corresponding to these two links, my functions in RSVP Controller look like these.
[Authorize, HttpPost]
public ActionResult Register(int id)
{
Event event = eventRepository.GetEvent(id);
if (event == null)
return Content("Event not found");
if (!event.IsUserRegistered(User.Identity.Name))
{
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
event.RSVPs.Add(rsvp);
eventRepository.Save();
}
return Content("Thanks, you are registered.");
}
[Authorize, HttpPost]
public ActionResult CancelRegistration(int id)
{
RSVP rsvp = eventRepository.GetRSVP(id);
if (rsvp == null)
return Content("RSVP not found");
if (rsvp.Event.IsUserRegistered(User.Identity.Name))
{
eventRepository.DeleteRSVP(rsvp);
eventRepository.Save();
}
return Content("Sorry, we won't be seeing you there!");
}
Both of these seem to work without any issues. Now I want to make it a little fancier by doing either of these two:
1) Return an AJAX link from controller so that when you register, you get cancel registration link shown to you without page refresh.
2) Somehow make the view rendering refreshed when the controller method has finished executing so the first code block in my question gets executed after the click of any of the AJAX links. So clicking on register will register you and show you cancel link and clicking on cancel will cancel your registration and show you register link.
Any help would be greatly appreciated.
Thanks.

You could by using jQuery show and hide these links.
I never use the Ajax.ActionLink, I do my AJAX without the helper but I think it should look loke this :
Ajax.ActionLink("Click here if you can't make it!", "CancelRegistration", "RSVP", new { id = Model.RSVPs.FirstOrDefault(r => r.AttendeeName.ToLower() == User.Identity.Name.ToLower()).RSVPID }, new AjaxOptions { UpdateTargetId = "QuickRegister", OnSuccess = "ShowHideLinks" }, new { id = "cancel-link", #style = "display:none"})
Ajax.ActionLink("RSVP for this event", "Register", "RSVP", new { id=Model.EventID }, new AjaxOptions { UpdateTargetId="QuickRegister", OnSuccess = "ShowHideLinks" }, new { id = "register-link"})
And some javascript/jQuery to initialize the current display link :
function ShowHideLinks() {
$('#register-link').toggle();
$('#cancel-link').toggle();
}
<%: if(Model.HasRSVP(Context.User.Identity.Name)) { %>
ShowHideLinks();
<%: } %>
Hope this help!

You can set the links using jQuery. I see you are passing Content from both the action methods... You can use $.post() in jQuery to execute these action and in the success eventhandler compare the returned content (you would need to send something which is more easy to compare than the current strings) and set the links appropriately.

Related

Unable to add HTML.BeginForm inside ASP.NET WebGrid

I have the following code inside my asp.net MVC-4 razor view:-
gridcolumns.Add(new WebGridColumn()
{
CanSort = false,
Format =
(item) =>
{
var banner = item.Value as Sales.Models.DeleteAllRequest;
if (!banner.Approved)
{
return Html.ActionLink("Approve", "DeleteRequestDeleteAll", "Customer", new { customerid = banner.CustomerID, requestid = banner.ID },
new AjaxOptions
{
Confirm = "Are You sure You want to delete (" + banner.CustomerName.ToString() + ")",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
});
}
return "";
}
});
The above code will add <a> link inside the ASP.NET web grid column. but since i am doing a Delete action so i should be sending Post request instead of Get request. so i am not sure how i can use Html.BeginForm instead of Html.ActionLink inside my above code?
Thanks

Asp.net MVC Ajax Button to retrieve a single data

I want to retrieve the first record in my database when ever I click the Ajax button, right now whenever I click my button it returns a List of my Record, I just want to retrieve the first record then when I click it again, returns the second record, is that even possible?
Here is my Ajax button :
#Ajax.ActionLink(" ", "BtnNext", null#*new { count = count + 1}*#, new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "current"
}, new { #class = "Middle-next dim btn btn-large-dim", #id = "Link1"})
Here is the controller for the Ajax button :
public PartialViewResult BtnNext()
{
var model = db.Queues.OrderBy(x => x.QueueNumber);
return PartialView("_queuenumber", model);
}
Thankyou so much, newbie <<
Try this
var model = db.Queues.ToList().OrderBy(x => x.QueueNumber).Take(1);

Paging on Partial View

I have a main view with a partial view.
The partial view allows paging, I am using Bootstrap.
Controller:
public ActionResult Main()
{
return View();
}
//[ChildActionOnly]
public ActionResult _Partial(int page)
{
Model = //returns records for requested page
return View(Model);
}
View:
<ul class="pagination">
#for (int i = 1; i <= model.TotalPages; i++)
{
<li>#Html.ActionLink(i.ToString(), "_Partial", new { page = i, })</li> }
}
</ul>
My problem is, although the paging works, selecting a page is calling the _Partial Action directly ( after I removed [ChildActionOnly]
So on paging it loads the Partial View only without the Main View which it forms part of...therefor it is missing the 'frame' provided by the Main View or any formatting.
Should I be following a different approach or is there a way to call a Partial Action and it’s Main Action?
I guess I would have liked to do something like…
<li>#Html.ActionLink(i.ToString(), "Main + _Partial", new { page = i, })</li>
Or how can I get Bootstrap Paging (I don't want to go the Ajax route) to work on a Partial View?
If you don't want to use ajax, then you have to return the whole page. Here an example for your case:
Controller:
public ActionResult Main()
{
return View();
}
public ActionResult SomeAction(int page) //Name this as your like
{
// I use viewbag here for convenience,
//you should consider to create new view model if necessary.
ViewBag.PageNum = page;
return View();
}
//[ChildActionOnly]
public ActionResult _Partial(int page)
{
Model = //returns records for requested page
return View(Model);
}
View "SomeAction.cshtml":
#*Put your Main page content here*#
#Html.Action("SomeAction", "YourControllerName", new { page = ViewBag.PageNum })
#*Put your Main page content here*#
And Your pagination should change to:
<ul class="pagination">
#for (int i = 1; i <= model.TotalPages; i++)
{
<li>#Html.ActionLink(i.ToString(), "SomeAction", new { page = i, })</li> }
}
</ul>
Keep in mind that I created the "SomeAction" only because I don't know what exactly does your "Main" action do. If the "Main" is simply the 1st page, then you should merge the "SomeAction" and "Main" into one:
public ActionResult Main(int page = 1)
{
ViewBag.PageNum = page;
return View();
}

ASP.NET MVC Delete Action Link with confirm

<td>
<%= Html.ActionLink("Delete", "DeleteUser", new RouteValueDictionary(new {uname=item.UserName}), new { onclick = "return confirm('Are you sure you want to delete this User?');" }) %>
</td>
In Global.asax.cs
routes.MapRoute(
"DeleteUser",
"Account.aspx/DeleteUser/{uname}",
new { controller = "Account", action = "DeleteUser", uname = "" }
);
In ActionContorller.cs
public ActionResult DeleteUser(string uname)
{
//delete user
}
the value of uname in the controller is being passed is empty string("").
Try like this:
<%= Html.ActionLink(
"Delete",
"DeleteUser",
"Account",
new {
uname = item.UserName
},
new {
onclick = "return confirm('Are you sure you want to delete this User?');"
}
) %>
Then make sure that the generated link is correct:
Delete
Also note that using a plain GET verb for an action that modifies the state on the server is not recommended.
Here's what I would recommend you:
[HttpDelete]
public ActionResult DeleteUser(string uname)
{
//delete user
}
and in the view:
<% using (Html.BeginForm(
"DeleteUser",
"Account",
new { uname = item.UserName },
FormMethod.Post,
new { id = "myform" })
) { %>
<%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
<input type="submit" value="Delete" />
<% } %>
and in a separate javascript file:
$(function() {
$('#myform').submit(function() {
return confirm('Are you sure you want to delete this User?');
});
});
You might also consider adding an anti forgery token to protect this action against CSRF attacks.

MVC 1.0 Ajax.BeginForm() submit inside an Html.BeginForm()

I have a View for creating a new account in my application. This view starts with Html.BeginForm() and hits the right controller (Create) no problems.
I decided to add an Ajax.BeginForm() so that I could make sure an account with the same name doesn't already exist in my application.
When I click the submit using either button it goes to the same controller (Create). To try and differentiate which submit button was clicked, I put in a check to see if the request is Ajax then try to run a different code path. But Request.IsAjaxRequest() doesn't fire. What is my best bet to implement this functionality in an existing form with MS Ajax?
<% using (Html.BeginForm()) {%>
..............
<% using(Ajax.BeginForm("Echo",
new AjaxOptions() { UpdateTargetId = "EchoTarget" }))
{ %>
Echo the following text:
<%=Html.TextBox("echo", null, new { size = 40 })%>
<input type="submit" value="Echo" />
<% } %>
<div id="EchoTarget">
controller code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(User newUser)
{
if (Request.IsAjaxRequest())
{
return Content("*you hit the ajax button");
}
else
{ //regular create code here.....
}
</div>
If you insist on multiple form usage..use Javascript in a some function like this
<SCRIPT>
function InnerFormSubmitter(dataForm, actionForm) {
actionForm.innerHTML = dataForm.innerHTML;
actionForm.submit();
}
</SCRIPT>
<form name="yourButton" action="ValidateSomething" method="post"></form>
<form name="mainForm" action="SavedData" method="post">
<input type="textbox" name="text1">
<input type="textbox" name="text2">
<button name="validateUserButton" id="FormButton" onChange=
"InnerFormSubmitter (this.form, document.getElementById('yourButton'))">
</button>
</form>
Hope this helps!
Addendum on jQuery usage for your scenario:
Since you wanted a link:
Check Availability
function isValidUser(userId) {
var url = "<CONTROLLER>/<ACTION>/" + userId;
$.post(url, function(data) {
if (data) {
// callback to show valid user
} else {
// callback to show error/permission
}
});
}
And you controller should have:
[AcceptVerbs("POST")]
public bool IsValidUser(int id) {
// check availability
bool allow = CheckUser();
// if allow then insert
if (allow) {
//insert user
return true;
} else {
return false;
}
}
Further Update on jQuery:
Instead of
document.getElementById('UserIdent').value
you can use
$('#UserIdent').val();
Update on JSON usage
The JsonResult class should be used in the Controller and $.getJson function in the View.
$(function() {
$('#yourLinkOrButton').click(function() {
$.getJSON("<CONTROLLER>/GetUserAvailability/", null, function(data) {
$("#yourDivorLablel").<yourFunctionToUpdateDiv>(data);
});
});
public JsonResult GetUserAvailability()
{
//do all validation and retrieval
//return JsonResult type
}
You cannot nest forms, ever, in any HTML page, no matter how you generate the form. It isn't valid HTML, and browsers may not handle it properly. You must make the forms siblings rather than children.

Resources