ASP.NET MVC design issue - c#

I have a main view with 2 partial views (a gridview and a callback panel)
This main view receives a IEnumerable<Model> and the panel just receives a Model.
When the view is initially called, the partial view of the panel is filled with an empty model so it is empty.
But I want to re render the panel once I click Edit in my GridView.
How can I achieve this?
I currently have an #Html.ActionLink in the Edit button but its not working since it will create a new view instead of re render the partial view of the panel.
Any clues?
EDIT:
this is my Edit:
Html.ActionLink("Edit", "EditConfig", new { id = DataBinder.Eval(c.DataItem, "QueueMonitorConfigurationsID") })
Function that the edit link calls:
[HttpGet]
public ActionResult EditConfig(int id)
{
StorageConfigurationModel resultForPanel = new StorageConfigurationModel { };
IEnumerable<StorageConfigurationModel> configList = (IEnumerable<StorageConfigurationModel>)Session["ConfigurationList"];
foreach (StorageConfigurationModel configModel in configList)
{
if (configModel.QueueMonitorConfigurationsID == id)
{
resultForPanel = configModel;
break;
}
}
return PartialView("cbpnlNewUpdateConfigs", resultForPanel);
}
Main view containing the partial views:
#model IEnumerable<BPM.Website.Models.StorageConfigurationModel>
#Html.Partial("gvConfigurations", Model)
#Html.Partial("cbpnlNewUpdateConfigs", new BPM.Website.Models.StorageConfigurationModel { QueueMonitorConfigurationsID = -1 })

I currently have an #Html.ActionLink in the Edit button
You could use AJAX. For example you could replace this Html.ActionLink with an Ajax.ActionLink and include the jquery.js and jquery.unobtrusive-ajax.js scripts (in that order) to make it act as an AJAX call. For example:
#Ajax.ActionLink(
"click to edit record",
"Edit",
new { id = item.Id },
new AjaxOptions { UpdateTargetId = "editContainer" }
)
When the link is clicked the Edit controller action will be invoked using an AJAX request and the id of the current item will be passed as parameter. When this AJAX request completes a DOM element with id="editContainer" will be updated with the results of this AJAX call. So your Edit controller action should return a partial view containing the record to be edited.

Solved with an Ajax POST
$.ajax({
type: "POST",
url: url,
data: data,
success: success,
dataType: dataType
});

Related

jQuery post to controller and redirect to ASP.NET MVC view

I have some checkboxes and a button (not in a form).
When the button is clicked, I have some jQuery and I am creating a post model which contains the values of the checked boxes and posting to a controller.
The controller then creates view models and I want to redirect the user to the correct view, passing the view model in to the view.
jQuery:
$.ajax({
url: AppSettings.baseUrl + "BOM/getMultiBOM",
type: 'POST',
data: JSON.stringify(data)
});
Controller:
[HttpPost]
public ActionResult getMultiBOM(multiBOMPostModel multiBomsPostModel)
{
BOM bom = null;
foreach (int value in multiBomsPostModel.bomsArray)
{
bom = db.BOMs.Find(value);
}
BOMViewModel viewModel = getViewModel(bom, null);
return RedirectToAction("OpenMultiBOM", new { viewModel = viewModel, bom = bom });
}
public ActionResult OpenMultiBOM(BOMViewModel viewModel, BOM bom)
{
viewModel.projectModel = new ProjectViewModel
{
project = bom.Project
};
return View(viewModel);
}
It is probably a bit of a mess.
I think the jQuery is necessary to pass the checkbox values to the controller.
When I use RedirectToAction to the method which then returns the view, the model is not being passed through, presumably as it is sending the model as a query string.
The view model is not simple and contains lists, IEnumerables, and nested models.
Can anyone help with the most efficient way to redirect/return the view while passing the view model?
Answer: I kept the ajax to post my checkbox values to the controller
$.ajax({
url: AppSettings.baseUrl + "BOM/getMultiBOM",
type: 'POST',
data: JSON.stringify(dataArr),
}).done(function (result) {
location.href = "/BOM/OpenMultiBOM";
});
In my controller, I assigned the posted values to a postModel and then stored them in TempData. The key here was to return a Json value which would then allow the redirect on the client side to take place.
public ActionResult getMultiBOM(multiBOMPostModel multiBOMPostModel)
{
TempData["BOMs"] = multiBOMPostModel;
return Json("success");
}
I then had another HttpGet method which would load after the page is redirected by the Ajax result and cast the TempData to an object.
[HttpGet]
public ActionResult OpenMultiBOM(int? BomMarkupMessage = null)
{
var bomIds = TempData["BOMs"] as multiBOMPostModel;
}
I would persist the viewmodel server side, perhaps in a session variable, or perhaps as a TempData (TempData typically only lives until the next request), and pass a key for the session variable to the second controller in the case of session variable, or use the TempData directly in your view in the case of TempData. This would avoid passing the whole object back and forth multiple times.
So the way that i have done this before is to have an empty div in DOM.
<div id="partialViewContent">
<!-- Content will be loaded later. -->
</div>
If you have a default view, you'll need to set it to load from URI using the below snippet.
$("#partialViewContent").load("Controller/Action",
function (response, status) {
if (status !== "success") {
console.log("An error has occured when attempting to load partial view.");
}
});
When you post to your controller action via JQUERY, have the action return a partial view with the model. (Assume model is relevant to each partial view).
Then when your ajax is complete, replace the content in partialViewContent with the POST response.

How to get selected index changed value in controller mvc c#

I am getting value in a dropdown list and I wanted to get the selected value in controller when user select any value from the dropdown list. My view is -
#using (Html.BeginForm("ApReport", "Sales", FormMethod.Post))
{
#Html.DropDownList("Ddl", null, "All", new { #class = "control-label"})
#Html.Hidden("rddl")
}
controller -
[HttpPost]
public ActionResult ApReport(ApReport Ddl)
{
string Ddlvalue = string.Empty;
if (Request.Form["rddl"] != null)
{
Ddlvalue = Request.Form["rddl"].ToString();
}
}
but I am not getting any value. Also, I donot want to use any submit button.
Thanks in advance
The use of Ajax allows you as the developer to update the main view without reloading the entire page, as well as send data to the server in the background.
This is how I would have accomplished this task.
Firstly, I would have created an action in my controller which returns a JsonResult. This will return a JSON object to your calling jquery code, that you can use to get values back into your views. Here is an example of the action method.
[HttpGet]
public JsonResult YourActionName(string selectedValue) //Assuming key in your dropdown is string
{
var result = DoYourCalculation(selectedValue);
return Json(new { myResult = result }, JsonRequestBehavior.AllowGet);
}
Now, you need to add your jquery code. I would recommend you place this in a seperate javascript file referenced by your view.
Here is the JQuery code, with the ajax call to the Action in your controller. The Ajax call to the server is initiated by the 'change' event of your DropDown, handled in JQuery, as can be seen below.
$(function () {
$(document)
.on('change', '#Ddl', function(){
var valueofDropDown = $(this).val();
var url = '/YourControllerName/YourActionName';
var dataToSend = { selectedValue: valueofDropDown }
$.ajax({
url: url,
data: dataToSend,
type: 'GET',
success: function (dataReceived) {
//update control on View
var receivedValue = dataReceived.myResult ;
$('YourControlIDToUpdate').val(receivedValue);
}
})
});
};

Redirect within partial view in MVC

I have kind of a weird scenario. I'm creating a site using the ASP.NET MVC Framework that contains a profile page which has a user's picture, info, etc. I have a view called Profile which loads partial views using the Ajax action link into a div. Here is an example:
#Ajax.ActionLink("Basic Info", "Index", "BasicInfo",
new {id=Model.UserName},new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "content",
HttpMethod = "GET"
})
The Index action of BasicInfo just shows the user's basic information. I want to have an edit link in that partial view that when pressed loads another action method, Edit where I can edit the values (another partial view). I have a couple of questions:
1) I didn't make Profile a layout even though it would be similar to a master page in ASP.NET because it would need a controller. Is there a way to create a layout that has its own controller?
2) How do I do a redirect within a partial view without doing a postback i.e. updating the div holding the partial view that was previously called by Ajax to an edit view?
3) I hope this all makes sense. I would see a profile with the person's basic information and I can press edit within that view and the edit view of that basic information controller is loaded into the div without doing a postback. What would be the best way to accomplish this?
You will find this a it easier using the jQuery ajax methods rather than the Ajax.ActionLink() and Ajax.BeginForm() methods. In the main view
<button type="button" class="details" data-id="Model.UserName">View details</button>
<div id="content"></div>
var detailsUrl = '#Url.Action("Details", "User")';
var editUrl = '#Url.Action("Edit", "User")';
// Display the details view
$('.details').click(function() {
$.get(detailsUrl, { id: $(this.data('id') }, function(response) {
$('#content').html(response);
});
});
// Display the edit view
$('#content').on('click', '#edit', function() {
$.get(editUrl, { id: $(this.data('id') }, function(response) {
$('#content').html(response);
});
});
// Post the edit form and replace with the updated details view
$('#content').on('click', '#save', function() {
var id = $(this).data('id');
var data = $(this).closest('form').serialize();
$.post(editUrl, data, function(response) {
if (response) {
$.get(detailsUrl, { id: id }, function() {
$('#content').html(response);
});
} else {
// Oops
}
}).fail(function (result) {
// Oops
});
});
The above assumes a UserController with the following methods
public PartialViewResult Details(int ID) // or string?
{
// Get the user model based on the ID
return PartialView("_Details", model);
}
public PartialViewResult Edit(int ID) // or string?
{
// Get the user model based on the ID
return PartialView("_Edit", model);
}
public JsonResult Edit(UserModel model) // replace with the name of your model
{
// Save the model
return Json(true); // indicate success
}
where the partial views are
_Details.cshtml
#model UserModel
.... // display properties of the model
<button type="button" id="edit" data-id="Model.UserName">Edit</button>
_Edit.cshtml
#model UserModel
<form>
.... // controls for properties of the model
<button type="button" id="save" data-id="Model.UserName">Save</button>
</form>
I might be misunderstanding things.
I think you're trying to flip a display view of a part of a page for an edit view of that part of the page.
I'll keep things general, because there's not enough code to refer to directly.
You should register javascript event handlers against the various clicks that can take place (in a jquery closure in a separate file is my personal preference). Those handlers should request whichever actions (returning partial views) are required.
e.g. when someone clicks the edit link, the handler calls the /GetEditStuff action, gets the partial view, and on success, clears out the previous content of the parent div and replaces it with the partial view.

How to refresh my Partial View after Ajax Post in MVC?

So basically I'm trying to show some Profile Data in my MVC Application.
Right now, everytime I click on a date on my Telerik Kendo Calendar, I can refresh the whole page and update the data I want.
However, instead of refreshing the whole I just want to refresh the partial views that shows only the data that updates after selecting the date.
Index.cshtml
<!--CODE-->
#Html.Partial("_WorkingTimeData")
<!--CODE-->
_WorkingTimeData.cshtml
var workedTime = ViewData["WorkedTimeToday"];
var hoursPerDay = ViewData["HoursPerDayContract"];
<p>You worked #workedTime hours</p>
<p>Hours Per Day (Contract) #hoursPerDay Hours</p>
Yes, right now I'm ViewDatas and it works.
This is the ajax code in Index.cshtml
$.ajax({ url: '/Profile/Index',
dataType: "json",
type: "POST",
data: JSON.stringify(10),
success: function(returl){
alert('It worked');
location.href=returl.Url;
},
error: function(jqXHR,responseText,textStatus){ alert(jqXHR.responseText) } });
Controller
[HttpPost]
public ActionResult Index(string number){
//THINGS TO DO
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Profile");
return Json(new { Url = redirectUrl });
}
Well I'm very new to this, and I've been doing my research. However I still have some questions:
- Do I need to create a post method for _WorkingTimeData instead of Index like I have?
- Do I need to create a ViewModel for the Partial View?
Thanks
EDIT NUMBER 2 FOR VISHAL:
This didn't work at all, not even an alert, because, strangely, it doesn't recognise the calendar...
$("#calendar").kendoCalendar({
change : function() {
$.ajax({
url: "/Profile/WorkingTimeData",
type: "get"
}).done(function(data) {
$("#profile-timeline").html(data);
});
}});
It says $("#calendar").kendoCalendar is not a function (Telerik says that it's this way)
As for this, it reached the controller but didn't update anything:
function change() {
alert("Escolheste outro dia");
var calendar = $("#calendar").data("kendoCalendar");
var current = calendar.current();
alert(current);
$.ajax({
url: "/Profile/WorkingTimeData",
type: "get"
}).done(function(data) {
$("#profile-timeline").html(data);
});
}
I think it's because of the profile-timeline... It's a div in my view
Do I need to create a post method for _WorkingTimeData?
Yes, you need to create. But, Get would be fine too.
Do I need to create a ViewModel for the Partial View?
Not needed. If required you can create.
But, by looking at your partial view you are just using ViewData[""]. So, you need not to create any ViewModel.
Just create a method in Controller returning _WorkingTimeData PartialView.
And call that method by JQuery ajax on your DatePicker change event and replace the contents of the Div.
For example.
Controller
public PartialViewResult WorkingTimeData()
{
ViewData["WorkedTimeToday"]="NEW VALUE";
ViewData["HoursPerDayContract"] = "NEW VALUE";
return this.PartialView("_WorkingTimeData");
}
JavaScript
$("DATEPICKERELEMENT").change(function() {
$.ajax({
url: "/CONTROLLER/WorkingTimeData",
type: "get"
}).done(function(data) {
alert(data);
$("#divisionIdContainingPartialView").html(data);
}).fail(function() {
alert('error');
});
});
I wrote a post that details why you need to break the logic of thinking about partial views client-side. If you're interested you can find it here.
The TL;DR version is simply, all you have client-side is HTML. There's no knowledge about what was or was not rendered to the response via a partial view. As a result, the real question is "How do I change a portion of my HTML page based on an AJAX response?". In the simplest form, you simply select some element on the page and then alter its inner HTML. You can do that with some custom HTML created client-side or you can actually pass back an HTML document as your AJAX response and then insert that.

Display Success message on the same page when submit

I'm using Html.Beginform in view page and get the parameters using FormCollection to the controller i want to return the Success message on the same ViewPage as a result.i'm using following code,
public string InsertDetails(FormCollection collection)
{
string result = "Record Inserted Successfully!";
return result;
}
It shows the success message on the new page.How can i resolve this? what i have to return to get the Success message on the same page?
Personally, I'd pop the result string into the ViewBag.
public ActionResult InsertDetails(FormCollection collection)
{
//DO LOGIC TO INSERT DETAILS
ViewBag.result = "Record Inserted Successfully!";
return View();
}
Then on the web page:
<p>#ViewBag.result</p>
I have following Options.
1. Use Ajax Begin Form with AjaxOptions like below
#using (Ajax.BeginForm("ActionName", "ControllerName", new { area = "AreaName" }, new
AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "alert('Success');" //This will execute once the Ajax call is finished.
}, null))
{
<input type="submit" name="nameSubmit" value="Submit" />
}
2. Use JQuery to Manually Setup the XHR Request
$.ajax({
url: "#Url.Action("ActionName", "ControllerName", new { area = "AreaName" });",
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({param : Value})
})
.done(function () { alert('Success');}) //This will execute when you request is completed.
.fail(function () { })
My Suggestions
There are following disadvantages while using the FormCollection
Point - 1
In case FormCollection is being used...It will be mandatory to Type Cast the Primitive Type Values un-necessarily because while getting the entry of specific Index of the System.Collections.Specialized.NameValueCollection, value being returned is of type String. This situation will not come in case of Strongly Typed View-Models.
Issue - 2
When you submit the form and goes to Post Action Method, and View-Model as Parameter exists in the Action method, you have the provision to send back the Posted Values to you View. Otherwise, write the code again to send back via TempData/ViewData/ViewBag
Point - 3
We have Data Annotations that can be implemented in View Model or Custom Validations.
ASP.Net MVC simplifies model validatons using Data Annotation. Data Annotations are attributes thyat are applied over properties. We can create custom validation Attribute by inheriting the built-in Validation Attribute class.
Point - 4
Example you have the following HTML
<input type="text" name="textBox1" value="harsha" customAttr1 = "MyValue" />
Question : How can we access the value of customAttr1 from the above eg from inside the controller
Answer : When a form get posted only the name and value of elements are posted back to the server. You can also use Hidden Fields to post the Attributes to Post Action method.
Alternatives : Use a bit of jQuery to get the custom attribute values, and post that along with the form values to action method
Another option is to rather put what you got in your custom attributes in hidden controls
That's the reason, I would always prefer to use View-Models
we can do it on Form inside view
#using (Ajax.BeginForm("Action", "Controller", new AjaxOptions { HttpMethod = "POST", OnSuccess = "Showmessage" }))
[HttpPost]
public ActionResult Test(TestViewModel model)
{
return Json(new {isok=true, message="Your Message" });
}
function Showmessage(data)
{
$('#Element').html('Successfully Submitted');
}

Categories

Resources