Passing data from partial view to parent view - c#

I am trying to pass a value from partial view to parent view. I tried the below which didn't worked for me. Can some one help me out how can I achieve this? By using the value that partial view returned, I am trying to hide a button which is in the parent view.
Parent View:
<div id="ProductCount">
#{
Html.RenderAction("ProductPartialView", "ProductList", new { area = "PR", ProductID = Model.ProductID, allowSelect = true});
}
<div class="saveBtnArea">
<input type="submit" value="Submit App" id="btn-submit" />
</div>
jQuery(document).ready(function () {
var ProductCount = jQuery("#ProductCount").val();
if (ProductCount == 0) {
jQuery("#btn-submit").hide();
}
else {
jQuery("#btn-submit").show();
}
});
Partial View:
<fieldset>
<div>
<input type="hidden" id="ProductCount" value="5" />
</div>
</fieldset>

You can implement change event for hidden input field like this
$('#ProductCount').change(function(){
var ProductCount = $(this).val();
if (ProductCount == 0) {
jQuery("#btn-submit").hide();
}
else {
jQuery("#btn-submit").show();
}
}).trigger('change');
$('#ProductCount').val(5);
$('#ProductCount').change(function(){
var ProductCount = $(this).val();
if (ProductCount == 0) {
jQuery("#btn-submit").hide();
}
else {
jQuery("#btn-submit").show();
}
}).trigger('change');
$('#ProductCount').val(5);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type='hidden' id='ProductCount' />
<button id='btn-submit'>Submit</button>

Related

TempData Dropping Data

I'm trying to persist a TempData value on a return PartialView(). It works correctly in one Post but not another and I'm stymied.
In the following action it works correctly and the value gets passed, via javascript redirect to the action that is using the value:
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult DeletetheFile(int attachmentid, string issueId)
{
string response = _adoSqlService.DeleteAttachment(attachmentid);
TempData["ID"]= issueId;
TempData.Keep();
return PartialView("_DeleteFile");
}
In the following action it is getting set properly (see the first image), but by the time it gets to the same action as the first one I showed it has changed (see second image).
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult EditFile(IFormCollection collection)
{
AttachmentModel model = new AttachmentModel();
model.attachmentId = Convert.ToInt32(collection["attachmentId"]);
model.aIssueAttachmentDescription = collection["aIssueAttachmentDescription"];
string response = _adoSqlService.EditFileDescription(model);
TempData.Remove("ID");
TempData["ID"] = collection["issueId"];
TempData.Keep();
return PartialView("_EditFile");
}
When it gets to the where I need it is now returning [string1] instead of the 20-003.
Both of the above actions run against a partial view in a modal pop-up. The following javascript captures the modal action and redirects the results to the Issue/Edit controller/action.
$('body').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$('body').find('.modal-content').html(data);
var isValid = $('body').find('[name="IsValid"]').val() == 'True';
if (isValid) {
$('body').find('#modal-container').modal('hide');
window.location.href = "/Issue/Edit";
}
});
})
The redirection seems to happen since the edit action is being called in both cases. It's just that in the second case it is not getting the correct value of the TempData value. Here is the start of the Edit action which resides in a different controller than the 2 actions above:
public ActionResult Edit(string id)
{
if (id == null)
{
id = TempData["ID"].ToString();
}
----------More Comments
So after working on this for the past 4 hrs I've come up with a work-around. I'm not sure this is the correct technique or not. What I ended up doing was adding a hidden input field on the partial views and then parsing the ajax response for that value.
var issueid = $(response).find('[name="issueidSaved"]').val();
window.location.href = "/Issue/Edit/?id=" + issueid
My concern now is that the issueid is now included in the query string and is visible in the URL.
Is this the correct method or should I go back to using TempData and trying to get that to work?
UPDATE
Hopefully I can explain this better. The goal is to get a TempData value into the following action in my Issues Controller which is tied to my Edit Page (Issues/Edit):
public ActionResult Edit(string id)
{
if (id == null)
{
id = TempData["ID"].ToString();
}
I have a modal on my Edit page that is populated with different partial views depending upon what is populating it. The partial views use the Attachment controller, while the Edit view uses the Issues Controller. I use Javascript/ajax to capture the submit from the partial views to close the modal and redirect to the Edit view so a refresh of the data affected by the partial views is reflected on the Edit view. The TempData value is working correctly when I submit the _DeleteFile, but not when I submit the _EditFile partial views in the modal.
Here is the common Javascript/ajax on the Edit view:
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
//Using this to scroll the page on the close of the modal/page refresh
$(document).ready(function () {
var JumpTo = '#ViewBag.JumpToDivId';
if (JumpTo != "") {
$(this).scrollTop($('#' + JumpTo).position().top);
}
});
//Using this to Capture the click that opens the modals
$('body').on('click', '.modal-link', function () {
var actionUrl = $(this).attr('href');
$.get(actionUrl).done(function (data) {
$('body').find('.modal-content').html(data);
});
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
//Using this to Capture the click that Submits the _EditFile,_DeleteFile,_CreateEdit forms on the modal
$('body').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$('body').find('.modal-content').html(data);
var isValid = $('body').find('[name="IsValid"]').val() == 'True';
var issueid = "";
issueid = $('body').find('[name="issueidSaved"]').val();
var jumpto = $('body').find('[name="jumpto"]').val();
if (isValid) {
$('body').find('#modal-container').modal('hide');
if (issueid == "")
{
window.location.href = "/Issue/Edit/?id=" + issueid + "&jumpto=" + jumpto;
}
}
});
})
//Using this to Capture the click that Submits the _UploadFile form on the modal
$(function () {
$('body').on('click', '.fileupload', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var fdata = new FormData();
$('input[name="file"]').each(function (a, b) {
var fileInput = $('input[name="file"]')[a];
if (fileInput.files.length > 0) {
var file = fileInput.files[0];
fdata.append("file", file);
}
});
$("form input[type='text']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
$("form input[type='hidden']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
$.ajax({
url: actionUrl,
method: "POST",
contentType: false,
processData: false,
data: fdata
}).done((response, textStatus, xhr) => {
var isValid = $(response).find('[name="IsValid"]').val() == 'True';
var issueid = $(response).find('[name="issueidSaved"]').val();
var jumpto = $(response).find('[name="jumpto"]').val();
if (isValid) {
$('body').find('#modal-container').modal('hide');
window.location.href = "/Issue/Edit/?id=" + issueid + "&jumpto="+jumpto;
}
});
})
});
$('body').on('click', '.close', function () {
$('body').find('#modal-container').modal('hide');
});
$('#CancelModal').on('click', function () {
return false;
});
$("form").submit(function () {
if ($('form').valid()) {
$("input").removeAttr("disabled");
}
});
</script>
Here is the _DeleteFile Partial view and the AttachmentController code that handles the submit:
<!--Modal Body Start-->
<div class="modal-content">
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
<input name="issueidSaved" type="hidden" value="#ViewBag.ID" />
<input name="jumpto" type="hidden" value="#ViewBag.JumpToDivId" />
<!--Modal Header Start-->
<div class="modal-header">
<h4 class="modal-title">Delete File</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<!--Modal Header End-->
<form asp-action="DeletetheFile" asp-route-attachmentid="#ViewBag.id" asp-route-issueId="#ViewBag.issueId" asp-controller="Attachment" method="post" enctype="multipart/form-data">
#Html.AntiForgeryToken()
<div class="modal-body form-horizontal">
Are you sure you want to delete the #ViewBag.title File?
<!--Modal Footer Start-->
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">No</button>
<input type="submit" class="btn btn-success relative" id="btnSubmit" data-save="modal" value="Yes">
</div>
<div class="row">
</div>
</div> <!--Modal Footer End-->
</form>
</div>
<script type="text/javascript">
$(function () {
});
</script>
<!--Modal Body End-->
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult DeletetheFile(int attachmentid, string issueId)
{
string response = _adoSqlService.DeleteAttachment(attachmentid);
ViewBag.ID = issueId;
ViewBag.JumpToDivId = "upload";
TempData["ID"]= issueId;
TempData.Keep();
return PartialView("_DeleteFile");
}
Here is the _EditFile partial view and the AttachmentController code:
Edit File
×
<form asp-action="EditFile" asp-controller="Attachment" method="post" enctype="multipart/form-data">
#Html.AntiForgeryToken()
<div class="modal-body form-horizontal">
<input name="issueId" type="hidden" value="#ViewBag.issueId" />
<input name="attachmentId" type="hidden" value="#ViewBag.attachmentId" />
<label class="control-label">#ViewBag.aFileName</label><br />
Make changes to description then select "Save Changes".<br />
<input name="aIssueAttachmentDescription" class="form-control formtableborders" id="titletext" value="#ViewBag.aIssueAttachmentDescription" />
<!--Modal Footer Start-->
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">No</button>
<input type="submit" class="btn btn-success relative" id="btnSubmit" data-save="modal" value="Save Changes">
</div>
<div class="row">
</div>
</div> <!--Modal Footer End-->
</form>
</div>
<script type="text/javascript">
$(function () {
});
</script>
<!--Modal Body End-->
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult EditFile(IFormCollection collection)
{
AttachmentModel model = new AttachmentModel();
model.attachmentId = Convert.ToInt32(collection["attachmentId"]);
model.aIssueAttachmentDescription = collection["aIssueAttachmentDescription"];
string response = _adoSqlService.EditFileDescription(model);
ViewBag.ID = collection["issueId"];
ViewBag.JumpToDivId = "upload";
TempData.Remove("ID");
TempData["ID"] = collection["issueId"];
TempData.Keep();
return PartialView("_EditFile");
}
When I inspect the TempData at the Issue/Edit action after the _DeleteFile submit it displays the following (which is correct):
When I inspect the TempData at the Issue/Edit action after the _EditFile submit it displays the following (which is incorrect):
You need to change
TempData["ID"] = collection["issueId"];
to
TempData["ID"] = collection["issueId"].ToString();
Because collection["issueId"] is Type Microsoft.Extensions.Primitives.StringValues rathar than Type String.
Here is a picture to show the Type:

MVCGrid.NET - How to reload the grid?

I am using MVCGrid.NET http://mvcgrid.net/
And I created a Non-Fluent grid http://mvcgrid.net/gettingstarted see Non-Fluent Example
GridDefinition<YourModelItem> def = new GridDefinition<YourModelItem>();
GridColumn<YourModelItem> column = new GridColumn<YourModelItem>();
column.ColumnName = "UniqueColumnName";
column.HeaderText = "Any Header";
column.ValueExpression = (i, c) => i.YourProperty;
def.AddColumn(column);
def.RetrieveData = (options) =>
{
return new QueryResult<YourModelItem>()
{
Items = new List<YourModelItem>(),
TotalRecords = 0
};
};
MVCGridDefinitionTable.Add("NonFluentUsageExample", def);
Now I have my grid appear when you submit a form, but when I submit the form again, I am expecting new data, but the grid does not reload or refresh or anything. It does't even reset when I refresh the page, I have to do a full reload of the page to reset it, which is lame, does anyone know how to refresh or reload the grid when I want to show new data?
I have even tried this: http://mvcgrid.net/demo/NoQueryOnPageLoad
But it did not reload or refresh.
PLEASE HELP!
It reloads, try this,
//model class
public class YourModelItem
{
public int Id { get; set; }
public string YourProperty { get; set; }
}
//controller
public class HomeController : Controller
{
private static List<YourModelItem> _modelItems = new List<YourModelItem>();
public ActionResult Index()
{
GridDefinition<YourModelItem> def = new GridDefinition<YourModelItem>();
GridColumn<YourModelItem> column = new GridColumn<YourModelItem>();
column.ColumnName = "UniqueColumnName";
column.HeaderText = "Any Header";
column.ValueExpression = (i, c) => i.YourProperty;
def.AddColumn(column);
def.RetrieveData = (options) => new QueryResult<YourModelItem>()
{
Items = _modelItems,
TotalRecords = 0
};
MVCGridDefinitionTable.Add("NonFluentUsageExample", def);
return View();
}
[HttpPost]
public JsonResult Add(YourModelItem item)
{
_modelItems.Add(item);
return Json(true, JsonRequestBehavior.AllowGet);
}
}
index.cshtml
#{
ViewBag.Title = "Home Page";
}
#using MVCGrid.Web
<div class="jumbotron">
<div id="form1">
<div class="form-group">
<label for="Id">ID</label>
<input type="number" class="form-control" id="Id" aria-describedby="Id" placeholder="Enter Id">
</div>
<div class="form-group">
<label for="YourProperty">YourProperty</label>
<input type="text" class="form-control" id="YourProperty" placeholder="Enter Your Property">
</div>
<button id="addItem">Submit</button>
</div>
<br />
#Html.MVCGrid("NonFluentUsageExample")
</div>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#addItem").click(function () {
var formData = { Id: $('#Id').val(), YourProperty: $('#YourProperty').val() };
$.ajax({
type: "POST",
url: "/Home/add",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(formData),
success: function(data) {
if (data) {
MVCGrid.reloadGrid('NonFluentUsageExample');
}
}
});
});
});
</script>
}
_layout.cshtml -> body
<body>
<div class="container body-content">
#RenderBody()
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
<script src="~/MVCGridHandler.axd/script.js"></script>
#RenderSection("scripts", required: false)
</body>
It adds item and reloads after "Submit".
Just have installed MVCGrid in new asp.net mvc - Install-Package MVCGrid.Net
Put these lines as above

action calling repeatedly using partialviews through list

I have list of resumes on which jobseeker can add note and send message to each of them. So I created partial view of resume. I used Ajax.Beginform method in partial views. On partial view there is submit option. Now when I call a specific resume partial view it calls the action and perform the job but not single time it repeats for each resume item. So why is the action called repeatedly? My View is here
#model NoteViewModel
<script src="~/Content/scripts/jquery-2.1.3.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<div class="app-tab-content" id="two-1">
#using (Ajax.BeginForm("AddNote","Employer",new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "result" }))
{
if(#Model!=null)
{
<input type="text" name="note" />
<input type="hidden" value="#Model.Res_id" name="res" />
<input type="hidden" value="#Model.Job_id" name="job" />
#*<button type="submit" value="AddNote"></button>*#
<input type="submit" id="AddNote" value="Add Note" />
}
}
<div id="result">
#if(ViewBag.NoteMessage!=null)
{
<p>ViewBag.NoteMessage</p>
}
</div>
</div>
Here is an action method
public ActionResult AddNote(string note, int? res, int? job)
{
jpc_resume_job jr = db.jpc_resume_job.Where(m => m.job_id == job && m.resume_id == res).FirstOrDefault();
if (ModelState.IsValid)
{
jr.note = note;
db.Entry(jr).State = EntityState.Modified;
db.SaveChanges();
ViewBag.NoteMessage = "Note Added Successfully";
return PartialView("Addnote");
}
ViewBag.NoteMessage = "Note Not Added Successfully";
return PartialView("Addnote");
}
I am calling this in searchresume view like this:
Foreach(var item in resume)
{
#Html.Partial("Addnote");
}
An image is attached for what exactly I want

render partial view from jquery not working

I have some issues with rendering a partial view using jquery. Even if it was asked more than once (here), I didn't found a solution that worked for me:
My view:
#model IEnumerable<OdeToFood.Models.RestaurantListViewModel>
#{
ViewBag.Title = "Home Page";
}
<form method="get" action="#Url.Action("Index")" data-otf-ajax="true" data-otf-target="#restaurantlist">
<input type="search" name="searchTerm" />
<input type="submit" value="Search By Name" />
</form>
#Html.Partial("_Restaurants", Model)
My partial view:
#model IEnumerable<OdeToFood.Models.RestaurantListViewModel>
<div id="restaurantList">
#foreach (var item in Model)
{
<div>
<h4>#item.Name</h4>
<div>#item.City, #item.Country</div>
<div>REviews: #item.CountOfReviews</div>
<hr />
</div>
}
</div>
otf.js:
$(function () {
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize()
};
$.ajax(options).done(function (data) {
var $target = $($form.attr("data-otf-target"));
$target.replaceWith(data);
});
return false;
};
$("form[data-otf-ajax='true']").submit(ajaxFormSubmit);
});
index action of my controller:
public ActionResult Index(string searchTerm = null)
{
var model =
_db.Restaurants
.OrderByDescending(r => r.RestaurantReviews.Average(a => a.Rating))
.Where(r => searchTerm == null || r.Name.StartsWith(searchTerm))
.Select(r => new RestaurantListViewModel
{
Id = r.Id,
Name = r.Name,
City = r.City,
Country = r.Country,
CountOfReviews = r.RestaurantReviews.Count()
}
)
.Take(10);
if (Request.IsAjaxRequest())
{
return PartialView("_Restaurants", model);
}
return View(model);
}
My issue is that nothing happens when I press search button. I've added an test alert like:
$.ajax(options).done(function (data) {
var $target = $($form.attr("data-otf-target"));
alert('test');
$target.replaceWith(data);
});
and the alert showed when I've clicked the search button, but in site nothing happens. Anyone knows what is my issue?
You have #restaurantlist as the target, whereas div id is actually restaurantList. Capital "L".

FileUpload: keep filenames when showing validation errors

I have the following file-upload code in C# using Asp.Net MVC. The problem is that when validation errors are shown, all the files chosen by the user are lost (input boxes are cleared). Is it possible to keep the input filenames in their original ordering without using javascript? What's the simplest approach?
Controller code
[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files)
{
//check for errors: if errors, ModelState.AddModelError(...);
if (!ModelState.IsValid) {
return View(files);
}
else {
//..........
}
}
View snippet
#using (Html.BeginForm("Index", "Uploader", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<input type="file" name="files" id="file1" />
#Html.ValidationMessage("1")
</div>
<div class="form-group">
<input type="file" name="files" id="file2" />
#Html.ValidationMessage("2")
</div>
//and 2 more file input fields
<div>
<input type="submit" value="Upload Files" class="btn btn-success btn-lg" />
</div>
}
In postback you can not retain same local path which will remain in type="file".
to do this think there are two way
1) in your current code if you find any file attached then save on server and maintain some flag in hidden field and hide/show your file control with text box( having only filename)
and send it back to browser. Then on next valid submit take that file name that you have already saved. and do your process.
2) On submit of form, copy(DOM copy) all your html control(file ,textbox, hidenfield ect..) in one iframe and submit that iframe.
In case anybody is still in search of a possibility, here is the work around that worked for me. I'm using MVC5. The idea is to use a session variable. I got the idea from ASP.Net Form.
My Model/ViewModel (only relevant properties):
public partial class emp_leaves
{
public string fileNameOrig { get; set; }
public byte[] fileContent { get; set; }
public HttpPostedFileBase uploadFile { get; set; }
}
In my controller (HttpPost):
//Check
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(emp_leaves emp_leaves)
{
if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
{
emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
Session["emp_leaves.uploadFile"] = emp_leaves.uploadFile; //saving the file in session variable here
}
else if (Session["emp_leaves.uploadFile"] != null)
{//if re-submitting after a failed validation you will reach here.
emp_leaves.uploadFile = (HttpPostedFileBase)Session["emp_leaves.uploadFile"];
if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
{
emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
emp_leaves.uploadFile.InputStream.Position = 0;
emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
}
}
//code to save follows here...
}
Finally within my edit view: here, i am conditionally showing the file upload control.
< script type = "text/javascript" >
$("#removefile").on("click", function(e) {
if (!confirm('Delete File?')) {
e.preventDefault();
return false;
}
$('#fileNameOrig').val('');
//toggle visibility for concerned div
$('#downloadlrfdiv').hide();
$('#uploadlrfdiv').show();
return false;
}); <
/script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
#model PPMSWEB.Models.emp_leaves #{ HttpPostedFileBase uploadFileSession = Session["emp_leaves.uploadFile"] == null ? null : (HttpPostedFileBase)Session["emp_leaves.uploadFile"]; } #using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data"
})) { #Html.AntiForgeryToken()
<div class="row">
#*irrelevant content removed*#
<div id="downloadlrfdiv" #((!String.IsNullOrEmpty(Model.fileNameOrig) && (Model.uploadFile==n ull || uploadFileSession !=null)) ? "" : "style=display:none;")>
<label>Attachment</label>
<span>
<strong>
<a id="downloadlrf" href="#(uploadFileSession != null? "" : Url.Action("DownloadLRF", "emp_leaves", new { empLeaveId = Model.ID }))" class="text-primary ui-button-text-icon-primary" title="Download attached file">
#Model.fileNameOrig
</a>
</strong>
#if (isEditable && !Model.readonlyMode)
{
#Html.Raw("&nbsp");
<a id="removefile" class="btn text-danger lead">
<strong title="Delete File" class="glyphicon glyphicon-minus-sign"> </strong>
</a>
}
</span>
</div>
<div id="uploadlrfdiv" #(!(!String.IsNullOrEmpty(Model.fileNameOrig) && Model.uploadFile==n ull) && !Model.readonlyMode ? "" : "style=display:none;")>
<label>Upload File</label> #Html.TextBoxFor(model => model.uploadFile, new { #type = "file", #class = "btn btn-default", #title = "Upload file (max 300 KB)" }) #Html.ValidationMessageFor(x => x.uploadFile)
</div>
</div>
}

Categories

Resources