ASP.NET MVC Delete Action Link with confirm - asp.net

<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.

Related

Ajax.Beginform + Partial view + Model state are not working together

I have the following Create action method inside my ASP .NET MVC :-
public ActionResult CreateVMNetwork(int vmid)
{
VMAssignIps vmips = new VMAssignIps()
{
TechnologyIP = new TechnologyIP() { TechnologyID = vmid},
IsTMSIPUnique = true,
IsTMSMACUnique = true
};
return PartialView("_CreateVMNetwork",vmips);
}
Which will render the following partial view:-
#model TMS.ViewModels.VMAssignIps
#using (Ajax.BeginForm("CreateVMNetwork", "VirtualMachine", new AjaxOptions
{
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "networktable",
LoadingElementId = "loadingimag",
HttpMethod= "POST"
}))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model=>model.TechnologyIP.TechnologyID)
<div>
<span class="f">IP Address</span>
#Html.EditorFor(model => model.TechnologyIP.IPAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.IPAddress)
<input type="CheckBox" name="IsTMSIPUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> |
<span class="f"> MAC Address</span>
#Html.EditorFor(model => model.TechnologyIP.MACAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.MACAddress)
<input type="CheckBox" name="IsTMSMACUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) />
</div>
<input type="submit" value="Save" class="btn btn-primary"/>
}
Inside the following main view, after clicking on the Ajax.actionlink:-
#Ajax.ActionLink("Add Network Info", "CreateVMNetwork","VirtualMachine",
new { vmid = Model.VirtualMachine.TMSVirtualMachineID },
new AjaxOptions {
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "AssignNetwork" ,
LoadingElementId = "progress"
}
)
</p>
<p><img src="~/Content/Ajax-loader-bar.gif" class="loadingimage" id="progress" /></p>
<div id ="AssignNetwork"></div>
Then when clicking on the “Save” button it will call the following action method:-
[HttpPost]
public ActionResult CreateVMNetwork(VMAssignIps vmip)
{
if (ModelState.IsValid)
{
try
{
repository.InsertOrUpdateVMIPs(vmip.TechnologyIP,User.Identity.Name);
repository.Save();
return PartialView("_networkrow",vmip);
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Error occurred: " + ex.InnerException.Message);
}}
return PartialView("_CreateVMNetwork", vmip);
}
When will render the following partial view _networkrow:-
#model TMS.ViewModels.VMAssignIps
<tr id="#Model.TechnologyIP.ID">
<td> #Model.TechnologyIP.IPAddress</td>
<td>#Model.TechnologyIP.MACAddress</td>
<td>#Ajax.ActionLink("Delete",
"DeleteNetworkInfo", "VirtualMachine",
new { id = Model.TechnologyIP.ID },
new AjaxOptions
{ Confirm = "Are You sure You want to delete (" + Model.TechnologyIP.IPAddress + ")" + "( " + Model.TechnologyIP.MACAddress + ").",
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})</td>
</tr>
All the above will work fine unless a model state error or an exception occurred , then in this case the table will be updated with the partial view and the model state will be displayed under the table with the fields. But I need to display the model state error on the same original view. So that I need the Ajax.begin form to update the table only if no exception or model state errors occured, and to display an error message inside the original partial view, not under the table.
Can anyone advice on how to solve this issue?
I don't get your question clearly, however I think you should place a <div> into your view where you want to show errors.
Then, if you got some errors on your processing, push some error messages through ViewBag to the model.
So, your action method will become like this:
[HttpPost]
public ActionResult CreateVMNetwork(VMAssignIps vmip)
{
if (ModelState.IsValid)
{
try
{
repository.InsertOrUpdateVMIPs(vmip.TechnologyIP,User.Identity.Name);
repository.Save();
return PartialView("_networkrow",vmip);
}
catch (Exception ex)
{
ViewBag.ErrorMessage = "Some messages...";
// also any other info you like
}
}
return PartialView("_CreateVMNetwork", vmip);
}
And that in your view like this:
<div>
<p>#ViewBag.ErrorMessage</p>
</div>
So, if you you got some errors, they'll be shown in that
Where is networktable defined? Remember that even if there is an exception (since you have caught it) or ModelState error, the ajax response will come back with status 200 and the OnSuccess will be executed. In the case of the save button, the returned response from the server will be inserted after the html of whatever networktable contains already. If you want special action to be taken when there is a failure, you have to change the response status on the server and catch it through a function on the client side called by OnFailure on the ajax form.

How to get the selected value of Html.DropDownListFor in aspx engine?

In Html (which I did not use) it's
<select>
<option value="B">Bubblegum</option>
</select>
In (from controller) Aspx it's
[HttpGet]
public ActionResult ViewMethod()
{
//Populate DropDownList
Treats = new List<KeyValuePair<string, string>>();
Treats.Add(new KeyValuePair<string, string>("Bubblegum", "B"));
ViewData["treats"] = new SelectList(Treats, "Value", "Key", SelectedTreat);
return View();
}
[HttpPost]
public ActionResult GeneratedContent(SomeModel model)
{
List<HalloweenTreats> ChewingGums = StoredProc(model.SelectedTreat);
return PartialView(ChewingGums);
}
then in the View:
<% using (Ajax.BeginForm("ViewMethod", "ControllerName", new AjaxOptions { UpdateTargetId = "DisplayValues" })) { %>
<%: Html.DropDownListFor(x => x.SelectedTreat, ViewData["treats"] as SelectList)%>
<input type = 'submit' name = 'submit' value = 'generate' />
<div id="DisplayValues"></div>
<% } %>
<%: Ajax.ActionLink("Generate", "RequestReportSummary", "Report", new { model = Model }, new AjaxOptions { UpdateTargetId = "GeneratedReport" })%>
How to get the selected value "B" of Html.DropDownListFor in aspx engine for me to send it as a string in the database?
The controller action you are posting to could take your model as parameter:
[HttpPost]
public ActionResult ViewMethod(SomeModel model)
{
// model.SelectedTreat will contain the selected value here
}

Recognize particular id in ajax form mvc3 from several hyperlink

I am currently working on a MVC3 project. I currently stuck on this portion.
I have this Ajax form which contains several hyperlink
#using (Ajax.BeginForm("Click", new AjaxOptions { UpdateTargetId = "showpage" }))
{
<a href="#" id="0" onclick='document.forms[0].submit()'>Link 0</a>
<a href="#" id="1" onclick='document.forms[0].submit()'>Link 1</a>
}
I have this function called "Click" in a controller to fire whenever there'a link clicked.
public ActionResult Click(String id)
{
// Action here
}
However, Whenever I click one of the hyperlinks, the click function receive id as "null". I want the function to know which hyperlink is click when enter the controller. Help needed :(
From my understanding, I think you're after something like this:
HTML:
<div id="showpage">
</div><br />
#using (Ajax.BeginForm("Click", "", new AjaxOptions { UpdateTargetId = "showpage" },
new { #id = "myAjaxForm" }))
{
#Html.ActionLink("Link 0", "Click", null, new { #id = "Link0", #data_val = "0", #class = "links" })
#Html.ActionLink("Link 1", "Click", null, new { #id = "Link1", #data_val = "1", #class = "links" })
#Html.Hidden("id", "");
}
SCRIPT:
<script>
$(function () {
$('a[class=links]').click(function (e) {
e.preventDefault();
$("input#id").val($(this).attr("data-val"));
$('form#myAjaxForm').submit();
});
});
</script>
CONTROLLER:
public ActionResult Click()
{
var m = new MyModel();
return View(m);
}
[HttpPost]
public ActionResult Click(string id)
{
return Content("ID = " + id, "text/html");
}
Hope this helps
I would recommend you to use a separate forms per button (which contrary to classic WebForms is something that you should not be afraid of in ASP.NET MVC) and of course use submit buttons instead of hyperlink which are the semantically correct element to submit a form:
#using (Ajax.BeginForm("Click", new { id = "0" }, new AjaxOptions { UpdateTargetId = "showpage" }))
{
<button type="submit" value="Link 0" />
}
#using (Ajax.BeginForm("Click", new { id = "1" }, new AjaxOptions { UpdateTargetId = "showpage" }))
{
<button type="submit" value="Link 1" />
}
Now inside your Click action you will get the correct id.
Instead of hyperlinks you can use submit buttons with the name property.
#using (Ajax.BeginForm("Click", new AjaxOptions { UpdateTargetId = "showpage" }))
{
<input type="submit" name="action" value="0" />
<input type="submit" name="action" value="1" />
}
public ActionResult Click(string action, ... )
{
// Action here
}

Controller AJAX method to return AJAX ActionLink

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.

Model not updating in MVC 2 application

I have a timesheet application that has a View where the user can select customers and tasks and add them to a dynamic table. This table is filled with the tasks and input fields for filling in hours worked.
For adding the new tasks in the dynamic table I use jQuery, so the savenewtask button is not a submit button. Instead I have a proper submit button for saving the hours when filled in.
The View is strongly typed to a model called TimesheetViewModel (see below). The controller passes the model to the View, and then the input fields are bound to properties in the model.
However, when I submit with the submit button and try to update the model in the Controller it doesn't update. It seemed from the Nerddinner tutorial (which I am using to learn MVC) that the model should automatically be updated using the values from the forms fields it had been bound to when you use UpdateModel(). But it doesn't. What am I doing wrong?
Here is all the relevant code:
View:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
//Hook onto the MakeID list's onchange event
$("#CustomerId").change(function () {
//build the request url
var url = "Timesheet/CustomerTasks";
//fire off the request, passing it the id which is the MakeID's selected item value
$.getJSON(url, { id: $("#CustomerId").val() }, function (data) {
//Clear the Model list
$("#TaskId").empty();
//Foreach Model in the list, add a model option from the data returned
$.each(data, function (index, optionData) {
$("#TaskId").append("<option value='" + optionData.Id + "'>" + optionData.Name + "</option>");
});
});
}).change();
});
</script>
<h2>Index</h2>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div>
<label for="Customers">
Kund:</label>
<%:Html.DropDownListFor(m => m.Customers, new SelectList(Model.Customers, "Id", "Name"), "Välj kund...", new { #id = "CustomerId" })%>
<label for="Tasks">
Aktiviteter:</label>
<select id="TaskId">
</select>
</div>
<p>
<input type="button" value="Save new task" id="savenewtask" />
</p>
<table width="100%">
<%--<% foreach (var task in Model.Tasks)--%>
<% foreach (var task in Model.WeekTasks)
{ %>
<tr>
<td>
<%: task.Customer.Name %>
</td>
<td>
<%: task.Name %>
</td>
<td>
<% foreach (var ts in task.TimeSegments)
{ %>
<input class="hourInput" type="text" size="2" id="<%: ts.Task.CustomerId + '_' + ts.TaskId + '_' + ts.Date %>"
value="<%: ts.Hours %>" />
<% } %>
</td>
</tr>
<% } %>
</table>
<input type="submit" value="Save hours" id="savehours" />
</fieldset>
<% } %>
</asp:Content>
From the Controller:
private TimesheetViewModel _model;
public TimesheetController()
{
_model = new TimesheetViewModel();
}
public ActionResult Index()
{
return View(_model);
}
[HttpPost]
public ActionResult Index(FormCollection collection)
{
try
{
UpdateModel(_model);
_model.Save();
return View(_model);
//return RedirectToAction("Index");
}
catch
{
return View();
}
}
The ViewModel:
public class TimesheetViewModel
{
private TimesheetContainer _model; //TimesheeContainer is an Entity Framework model
public TimesheetViewModel()
{
_model = new TimesheetContainer();
}
public IList<Customer> Customers
{ get { return _model.Customers.ToList(); } }
public IList<Task> Tasks
{ get { return _model.Tasks.ToList(); } }
public IList<Task> WeekTasks
{
get
{
//Get the time segments for the current week
DateTime firstDayOfWeek = DateTime.Parse("2010-12-05");
DateTime lastDayOfWeek = DateTime.Parse("2010-12-13");
List<TimeSegment> timeSegments = new List<TimeSegment>();
foreach (var timeSegment in _model.TimeSegments)
{
if(timeSegment.DateTimeDate > firstDayOfWeek && timeSegment.DateTimeDate < lastDayOfWeek)
timeSegments.Add(timeSegment);
}
//Group into tasks
var tasks = from timeSegment in timeSegments
group timeSegment by timeSegment.Task
into t
select new { Task = t.Key };
return tasks.Select(t => t.Task).ToList();
}
}
public IList<TimeSegment> TimeSegments
{ get { return _model.TimeSegments.ToList(); } }
public void Save()
{
_model.SaveChanges();
}
public void AddTimeSegments(Task task)
{
_model.AddToTasks(task);
_model.SaveChanges();
}
}
Partial class to get tasks for a specific week (only dummy week at this time for testing):
public partial class TimeSegment
{
public DateTime DateTimeDate
{ get { return DateTime.Parse(Date); } }
}
Why is the model not updating, and what can I change to make it work?
Put a breakpoint on your first ActionResult Index(), is that getting called when you do the submit? you may need [HttpGet] on it, otherwise I think it gets both.

Resources