Partial View not refreshing? - asp.net-mvc-4

My Controller method is
public ActionResult Index(string id = "All")
{
ViewBag.RefType = new SelectList(rep.getReferenceType());
List<Reference> reference = rep.getReference(id);
if (Request.IsAjaxRequest())
return PartialView("_ReferenceList", reference);
else
{
ViewBag.domain = "All";
return View(reference);
}
}
Second method calls the index
public ActionResult EditReference(Reference rf, int Dom)
{
Reference rf1 = null;
string dom = "";
if (ModelState.IsValid)
{
rf1 = rep.UpdateReference(rf);
if (Dom == 0)
{
dom = "All";
}
else
{
dom = rf1.Domain;
}
return RedirectToAction("Index", new { id =dom});
}
return View(rf1);
}
and my view is
#using (Ajax.BeginForm("EditReference", "Reference", new AjaxOptions { HttpMethod = "POST", OnSuccess = "closeDialog()", LoadingElementId = "divLoading" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
Html.RenderPartial("_Reference");
}
The problem is that the new edited data doesnt appear once the dialog is closed ...It displays the same old data...I tried another function
function closDlgAndRefresh{
$('.Dialog').dialog('close');
$('.ddlRndrPrtl').val($('.ddlRndrPrtl').val());
$('.ddlRndrPrtl').trigger('change');
}
and when I call this function onSuccess it does displays the data but the Index function is called twice which I don't wana do...Once when Index function is called from Edit function and 2nd when dropdown is triggered...

Got it fixed....
Forgot to add Updated TargetID in Ajax.BeginForm
#using (Ajax.BeginForm("EditReference", "Reference", new AjaxOptions { HttpMethod = "POST", LoadingElementId = "divLoading", InsertionMode = InsertionMode.Replace, UpdateTargetId = "DivTbl_Reference" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
Html.RenderPartial("_Reference");
}

Related

why the ajax request sent as non-ajax?

i have the following index view
#model VirtualCampus2.Models.EmployeeViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#using(Ajax.BeginForm("GetEmployee", "Employee",
new AjaxOptions
{
HttpMethod = "get",
InsertionMode = InsertionMode.Replace,
OnSuccess = "updateDivList",
UpdateTargetId = "divList" }))
{
#Html.DropDownListFor(m=>m.id, Model.DDLCollecton)
<input type="text" name="SearchString" />
<input type="submit" value="search" />
}
<div id="divList">
#Html.Partial("_EmployeeList", Model.Employees);
</div>
<script type="text/javascript">
function updateDivList() {
$('#divList').html();
}
</script>
its controller :
public class EmployeeController : Controller
{
//
// GET: /Employee/
testdbEntities db = new testdbEntities();
public ActionResult Index()
{
List<SelectListItem> ddlColl = new List<SelectListItem>
{
new SelectListItem{ Text="By Emp No", Value="1", Selected=true},
new SelectListItem{ Text="By Name", Value="2"}
};
var employees = db.Employees.Select(e => new EmployeeModel
{
EmpID=e.EmpId,
FirstName=e.FirstName,
LastName=e.LastName,
DeptId=e.DepartmentId,
DepartmentName=e.Department.Name
});
EmployeeViewModel evm = new EmployeeViewModel { DDLCollecton = ddlColl, Employees = employees };
return View(evm);
}
public ActionResult GetEmployee(string id, string SearchString)
{
IEnumerable<EmployeeModel> results=null;
if (id == "1")
{
var searchID = ( SearchString == "" ) ? 0 : int.Parse(SearchString);
results = db.Employees.Where( e => ( SearchString == "" || e.EmpId == searchID ) )
.Select(e => new EmployeeModel
{
EmpID = e.EmpId,
FirstName = e.FirstName,
LastName = e.LastName,
DeptId = e.DepartmentId,
DepartmentName = e.Department.Name
}).ToList();
}
else
{
}
return PartialView("_EmployeeList", results);
}
when i request the ajax it sends request as non-ajax call but gets the data as a regular http request, as shown on this video
why it happens and how do i fix this?

How can I return a model with an ActionLink?

I'm trying to get a model in a view and pass it to another controller but the model is null when passed to the other controller.
Controller - Here I send the model to render in my view:
[HttpPost]
public PartialViewResult Index(ReportesTabularesViewModel ModeloInput)
{
GetDatosTabularReportInput input = new GetDatosTabularReportInput { IdSensor = ModeloInput.sensor, FechaInicio = ModeloInput.FechaInicio, FechaFinal = ModeloInput.FechaFinal };
ReportesTabularesViewModel Modelo = new ReportesTabularesViewModel();
var Lista = new CaelusReporting.Datos.DatosApp().GetDatosTabularReport(input);
var s = Modelo.Sensores;
ViewBag.Sensores = s;
Modelo.Datos = Lista.GroupBy(x => x.Fecha).Select(y => new DatosViewModel
{
Fecha = y.Key,
EstacionSensorSensorNombre = y.First().EstacionSensorSensorNombre,
Datos = y
}
);
ViewBag.Modelo = ModeloInput;
return PartialView(Modelo);
}
View:
#model CaelusReporting.Web.Models.ViewModels.Datos.ReportesTabularesViewModel
#{
ViewData["temp"] = ViewBag.Modelo;
ViewBag.Title = Model.Datos.Select(y => y.EstacionSensorSensorNombre).FirstOrDefault();
List<CaelusReporting.Sensores.Dto.SensoresDto> sensores = ViewBag.Sensores;
}
<a class="menu-bar" data-toggle="collapse" href="#menu">
<span class="bars"></span>
</a>
<div class="collapse menu" id="menu">
<div class="list-inline">
#using (Ajax.BeginForm("Index", new AjaxOptions { UpdateTargetId = "Update", HttpMethod = "POST", InsertionMode = InsertionMode.Replace }))
{
<label>Sensor: </label>
<select data-placeholder="Escoja las estaciones" class="chosen-select-width" tabindex="8" name="sensor">
#foreach (var item in sensores.Where(x => x.estado == true))
{
<option value=#item.Id>#item.nombre</option>
}
</select>
<label>Fecha de Inicio: </label>
#Html.TextBoxFor(m => m.FechaInicio, null, new { type = "datetime-local", style = "max-width:235px; max-height:20px" })
<label>Fecha de Final: </label>
#Html.TextBoxFor(m => m.FechaFinal, null, new { type = "datetime-local", style = "max-width:235px; max-height:20px" })
<input id="Submit1" type="submit" value="Ver" />
}
Get Report in PDF
Get Report in XLS
Get Report in DOC
Get Report in CSV
</div>
</div>
Another controller - Here I try to import report that is in:
public ActionResult ExportReport(string DocType)
{
ReportesTabularesViewModel test = ViewData["temp"] as ReportesTabularesViewModel;
GetDatosTabularReportInput input = new GetDatosTabularReportInput { IdSensor = test.sensor, FechaInicio = test.FechaInicio, FechaFinal = test.FechaFinal };
var Lista = new CaelusReporting.Datos.DatosApp().GetDatosTabularReport(input);
ReportDocument rd = new ReportDocument();
rd.Load(Path.Combine(Server.MapPath("~/Reportess"), "Reporte.rpt"));
rd.SetDataSource(Lista);
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
switch (DocType)
{
case "PDF":
rd.Load(Path.Combine(Server.MapPath("~/Reportess"), "Reporte.rpt"));
try
{
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", "ReportePDF.pdf");
}
catch (Exception ex)
{
throw;
}
case "DOC":
rd.Load(Path.Combine(Server.MapPath("~/Reportess"), "Reporte.rpt"));
try
{
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.WordForWindows);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/msword", "ReporteDOC.doc");
}
catch (Exception ex)
{
throw;
}
case "XLS":
rd.Load(Path.Combine(Server.MapPath("~/Reportess"), "Reporte.rpt"));
try
{
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.Excel);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/vnd.ms-excel", "ReporteDOC.xls");
}
catch (Exception ex)
{
throw;
}
case "CSV" :
rd.Load(Path.Combine(Server.MapPath("~/Reportess"), ""));
try
{
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.CharacterSeparatedValues);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "text/csv", "ReporteCSV.csv");
}
catch (Exception ex)
{
throw;
}
default:
return null;
}
}
You can not pass ViewData between requests (actions). You need to serialize data somehow, in querysting for example. You can use RouteValueDictionary to do this.
you need to create Model for action ActionResult ExportReport(string DocType) like this:
public class ExportReportModel
{
public string DocType {get; set;}
// all fields which you required from ReportesTabularesViewModel
}
then your action will looks like this ActionResult ExportReport(ExportReportModel model) and you can render such a links:
Get Report in PDF
you can also use anonymous objects, but in case when you have more than 3 parameters I will organize those in some kind of structure.

Viewbag doesn't exist

I tried to do this:
var NewViewResult = new ViewResult { ViewName = "Error", ViewBag.error = "Error Here" };
I got these two errors
Invalid initializer member declarator
The name 'ViewBag' does not exist in the current context
That is my code:
public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled) return;
string actionName = filterContext.RouteData.Values["action"].ToString();
Type controllerType = filterContext.Controller.GetType();
var method = controllerType.GetMethod(actionName);
var returnType = method.ReturnType;
if (returnType.Equals(typeof(JsonResult))) if (filterContext.Exception is CustomException) filterContext.Result = new JsonResult() { Data = ((CustomException)filterContext.Exception).Type }; else filterContext.Result = new JsonResult() { Data = OurExceptionType.GeneralException };
else if (returnType.Equals(typeof(ActionResult)) || (returnType).IsSubclassOf(typeof(ActionResult))) filterContext.Result = new ViewResult { ViewName = "Error" ViewBag.error="SomeError" };
filterContext.ExceptionHandled = true;
}
ViewBag is a dynamic property you cannot pass it like this in a ViewResult.
Set value in ViewBag like this:
var NewViewResult = new ViewResult { ViewName = "Error" };
ViewBag.error = "Error Message";
and In View, you can simply access it without passing in the ViewResult:
<span>#ViewBag.error</span>
and if you really want to pass it in ViewResult,then don't use ViewBag, do like this:
var NewViewResult = new ViewResult { ViewName = "Error" };

DataAnnotations attributes on custom control

I've used a custom control (HTML Helper) to build an Autocomplete controller.
it works great, the only thing is the validation problem.
on the client side, the validation works fine when jquery.validation.js is out of the picture, (for empty text box it gives an error message).
if the user selects something from the autocomplete, so im fine.
but when the user input is just junk, then the HttpPost needs to handle the junk & return an error message to the user.
HOW??
also, i've seen a DataAnnotation called Remote, which can manage the validation on the client side, is it better ? if so, how can i add DataAnnotaion on a custom control ??
Thank's :)
here is my code:
Index.cshtml
#using (Html.BeginForm("Index", "Create"))
{
#Html.AutocompleteFor(Url.Action("AutoCompleteServiceProviders", "Create"), true, "ex. Shower", c => c.service_id, a => a.name)
<input type="submit" id="search" value="" />
}
AutoComplete.cs
private static MvcHtmlString CreateAutocomplete<TModel>(this HtmlHelper<TModel> helper, string actionUrl, bool? isRequired, string placeholder, params Expression<Func<TModel, object>>[] expression)
{
var builder = new StringBuilder();
foreach (var item in expression)
{
var attributes = new Dictionary<string, object>
{
{ "data-autocomplete", true },
{ "data-action", actionUrl }
};
if (!string.IsNullOrWhiteSpace(placeholder))
{
attributes.Add("placeholder", placeholder);
}
if (isRequired.HasValue && isRequired.Value)
{
attributes.Add("required", "required");
}
Func<TModel, object> method = item.Compile();
var value = (Object)null;
if ((TModel)helper.ViewData.Model != null)
{
value = method((TModel)helper.ViewData.Model);
}
var baseProperty = (string)null;
var hidden = (MvcHtmlString)null;
if (item.Body is MemberExpression)
{
baseProperty = ((MemberExpression)item.Body).Member.Name;
hidden = helper.Hidden(baseProperty, value);
attributes.Add("data-value-name", baseProperty);
}
else
{
var op = ((UnaryExpression)item.Body).Operand;
baseProperty = ((MemberExpression)op).Member.Name;
hidden = helper.Hidden(baseProperty, value);
}
attributes.Add("data-value-id", "service_id");
var automcompleteName = baseProperty + "_autocomplete";
var textBox = (MvcHtmlString)null;
if (value != null)
{
textBox = helper.TextBox(automcompleteName, value, string.Empty, attributes);
}
else
{
textBox = helper.TextBox(automcompleteName, null, string.Empty, attributes);
}
builder.AppendLine(hidden.ToHtmlString());
if (baseProperty == "name")
{
builder.AppendLine(textBox.ToHtmlString());
}
}
return new MvcHtmlString(builder.ToString());
}
You can get your validation from here:
var validation = htmlHelper.ValidationMessageFor(expression, null, new Dictionary<string, object>());
UPDATE:
I use TagBuilder to create tags. What I do with tagbuilder is add that validation to a span or div tag and let the unobtrusive javascript hide/show it when needed. It returns an MVCHtmlString you can just append it to the element you want to display it in

Form post passes null model - .NET MVC 4

I am using this post as reference
I am trying to get the Model that I passed to the view to post back to the HttpPost method of the controller when the input is clicked. However, the model, which in this case is just List, is null when it posts back.
I have included my code for reference. This is just a project for testing random stuff out so I apologize for the crappy code.
I have the following View code: (showing the whole code for completness)
#{
ViewBag.Title = "Home Page";
}
#using TestApp.MyObjects
#model List<Contact>
#Ajax.ActionLink("Show About", "About", new { id = "1" }, new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "contentDiv" })
#Ajax.ActionLink("Show Contact", "Contact", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "contentDiv" })
<div id="contentDiv"></div>
#using (Html.BeginForm())
{
<table>
#foreach (Contact c in Model)
{
<tr>
<td>
<button aboutnum0 = "#c.someValues[0]" aboutnum1 = "#c.someValues[1]" aboutnum2 = "#c.someValues[2]" class="nameButton">#c.name</button>
</td>
</tr>
}
</table>
<input value="#Model[0].name" />
<input value="#Model[0].name" />
<div id ="aboutContentDiv"></div>
<input type="submit" />
#ViewBag.myCoolValue
}
<script type="text/javascript">
$("button").click(function () {
$("#aboutContentDiv").empty();
$("#aboutContentDiv").append($("<div></div>").load("Home/About/" + $(this).attr("aboutnum0")));
$("#aboutContentDiv").append($("<div></div>").load("Home/About/" + $(this).attr("aboutnum1")));
$("#aboutContentDiv").append($("<div></div>").load("Home/About/" + $(this).attr("aboutnum2")));
});
</script>
The Following is my Comtroller Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestApp.MyObjects;
namespace TestApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
Contact c = new Contact();
c.name = "Some Name";
c.someValues = new List<string>();
c.someValues.Add("1");
c.someValues.Add("2");
c.someValues.Add("3");
Contact c1 = new Contact();
c1.name = "Some Name1";
c1.someValues = new List<string>();
c1.someValues.Add("4");
c1.someValues.Add("5");
c1.someValues.Add("6");
Contact c2 = new Contact();
c2.name = "Some Name2";
c2.someValues = new List<string>();
c2.someValues.Add("7");
c2.someValues.Add("8");
c2.someValues.Add("9");
List<Contact> clist = new List<Contact>();
clist.Add(c);
clist.Add(c1);
clist.Add(c2);
Session["myCoolValue"] = "Cool1";
TempData["myCoolValue"] = "Cool2";
return View(clist);
}
[HttpPost]
public ActionResult Index(List<Contact> contacts)
{
string name = contacts[0].name;
return View("Index",contacts);
}
public PartialViewResult About(string id = "")
{
ViewBag.Message = "Your app description page.";
About a = new About();
a.someValue = id + " _ modified by contoller";
ViewBag.myCoolValue = "Cool";
return PartialView("About",a);
}
public PartialViewResult Contact()
{
ViewBag.Message = "Your contact page.";
return PartialView("Contact");
}
}
}
Based on your reply to my comment, you need something like this:
// you can use foreach and have a counter variable or this
for (int i = 0; i < Model.Count; i++)
{
// you do not want to use a partial view so let's do it this way
// put this in an appropriate place in your code
// like inside a tr or div, it's up to you
#Html.TextboxFor(m => m[i].name)
}