Rendering PartialView to string inconveniences - asp.net-mvc

I'm developing ASP.NET MVC5 (Razor) project. I would like to render partial view into a DIV when Test ActionLink clicked, so code for Controller is this:-
public ActionResult Accion(string vista)
{
if (string.IsNullOrEmpty(vista) || !Request.IsAjaxRequest())
return View();
else
{
object vistaModelo = null;
if (vista.Contains("Usuarios"))
vistaModelo = new UsuariosVistaModelo();
string render = PartialView(vista, vistaModelo).RenderToString();
return Json(new { data = render });
}
}
Code for cshtml:-
<div class="menu">
#Html.ActionLink("Test","Accion","Navigation",new { vista = "~/Views/Soporte/Usuarios.cshtml" }, new { #class = "accion" })
<script>
//Dispara la acción en el controlador del servidor
$('.accion').live("click", function () {
$.ajax({
url:this.href,
type:'post',
success:function(data)
{
//data contiene el resultado devuelto por el servidor
$('.content').html(data);
},
error: function (req, status, error) {
alert(error);
}
});
//Se retorna falso para prevenir reenviar a otra pagina
return false;
});
</script>
</div>
<div class="content">
</div>
When I click on Test ActionLink, $('.accion').live("click" ... event is not triggered and go straighforward to Accion into controller. Please need help. Thanks

Some modifications in your code to make it working
** Modify your action to
#Html.ActionLink("Test","Accion","Navigation",new { vista = "~/Views/Soporte/Usuarios.cshtml" }, new { #class = "accion", onclick = "javascript:return false;" })
Now anchor default behaviour would not work.
** Now modify your Jquery like
//Dispara la acción en el controlador del servidor
$('.accion').click(function () {
$.ajax({
url:this.href,
type:'post',
data : {"vista" : "~/Views/Soporte/Usuarios.cshtml"},
success:function(data)
{
//data contiene el resultado devuelto por el servidor
$('.content').html(data);
},
error: function (req, status, error) {
alert(error);
}
});
//Se retorna falso para prevenir reenviar a otra pagina
return false;
});
//Add Post on the top of action
[HttpPost]
public ActionResult Accion(string vista)
{
if (string.IsNullOrEmpty(vista) || !Request.IsAjaxRequest())
return View();
else
{
object vistaModelo = null;
if (vista.Contains("Usuarios"))
vistaModelo = new UsuariosVistaModelo();
string render = PartialView(vista, vistaModelo).RenderToString();
return Json(new { data = render });
}
}
Also use on/click instead of live

Some modification on Jquery level
// code
success:function(data)
{
$('.content').html(data.data);
},
error: function (req, status, error) {
alert(error);
}
// code
try to replace
$('.content').html(data); to $('.content').html(data.data); Here 2nd data is the parameter which holds the value on controller.

Related

Received files from axios in c# mvc

I trying, searching since several hours and no success
I've a mvc/vue/quasar application where I try to upload a photo from a button
In my cshtml file
<q-input type="file" ref="myFileAvatar" v-on:change="handleFileUpload()" v-model="avatar" style="display:none" accept="image/*"/>
<q-btn round color="primary" icon="cloud_upload" #click="getAvatar" ></q-btn >
I send file from my js, method section
getAvatar: function () {this.$refs.myFileAvatar.$el.click()},
handleFileUpload() {
//const files = Array.from(this.avatar).filter((file) => { return file.size < 102500 && file.type.substring(0, 6) == 'image/' });
let formData = new FormData();
formData.append('ownerID', this.profildata.ownerid);
formData.append('file', this.avatar);
axios.post('/forms/default/uploadProfilImage', formData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then(function (response) {
//TODO
});
}
And in my controler
public JsonNetResult uploadProfilImage(Guid ownerID, HttpPostedFileBase file)
{
resultModel resultUpload = new resultModel();
if (this.Request.Files != null && this.Request.Files.Count == 1)//My old version with q-uploader
{
}
else { resultUpload.status = resultMessage.resultValue.error; resultUpload.message = "Oups, ou sont les fichiers"; }
return JsonNetResult.JsonNet(resultUpload);
}
Problem : file is null even if in developper mode in chrome, I see file is a FileList
ownerID is good... I try several type instead of HttpPostedFileBase but nothing (execpt object give a array of string...)
thanks for your help
finally...
It's a type of parameter problem like I thougth
handleFileUpload() {
if (this.avatar[0].size < 102500 && this.avatar[0].type.substring(0, 6) == 'image/') {
let formData = new FormData();
formData.append('file', this.avatar[0]);//One file
formData.append('ownerID', this.profildata.ownerid);
let self = this
axios.post('/forms/default/uploadProfilImage', formData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then(function (response) {
if (response.data.status == 0) { self.profildata.idFichierAvatar = response.data.model.id; } else { self.showNotifError(response.data.message); }
this.avatar = '';
});
}
else { this.showNotifError("L'image ne répond pas aux critères");}
}
and mvc side
[HttpPost]
public JsonNetResult uploadProfilImage(HttpPostedFileBase file,Guid ownerID )
{
resultModel resultUpload = new resultModel();
if (file != null)
{
}
else { resultUpload.status = resultMessage.resultValue.error; resultUpload.message = "Oups, ou sont les fichiers"; }
return JsonNetResult.JsonNet(resultUpload);
}
##UPDATE : Multiple##
And for multiple files
in q-input add multiple property
in server side :
[HttpPost]
public JsonNetResult uploadProfilImage(HttpPostedFileBase[] files,Guid ownerID )
And To send files from js
handleFile() {
let formData = new FormData();
for (var i = 0; i < this.newfiles.length; i++) {
let fichier = this.newfiles[i];
formData.append('files[' + i + ']', fichier);
}
formData.append('ownerID', this.ownerid);
let self = this
axios.post('/files/joinFile/uploadFiles', formData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then(function (response) {
if (response.data.status == 0) { self.files = response.data.model; } else { self.showNotifError(response.data.message); }
this.newfiles = '';
});
}
I hope it's full for everyone who have same problem :-)

jquery autocomplete passing parameters

I need help to pass parameters through JQuery's autocomplete. I have an input:
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" name="searchName" id="searchName" placeholder="Nom et/ou prénom" />
inside a form. When you type, an jquery autocomplete function launches a search in Active Directory and shows result in the drop down list:
$(document).ready(function () {
$("#searchName").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/SearchUserWhileTyping",
type: "GET",
data: { name: $("#searchName").val() },
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
$("#searchName").html(''),
response($.map(data, function (item) {
return {
label: item
}
}));
}
});
},
minLength: 4
})
});
$(document).ready(function(){
$('#searchName').on('autocompletechange change', function () {
$('#searchValue').html('You selected: ' + this.value);
}).change()});
For now I could only do it after a form validation: form is validated -> I load the users found and their unique id -> click on one link and it shows the user info thanks to their unique id passed through. What I want to do is: If you click on one of the autocomplete choices, it directly shows the information of your user.
Here is the code for the search while you type:
[HttpGet]
public ActionResult SearchUserWhileTyping(string name)
{
ADManager adManager = new ADManager();
List<string> lastName = adManager.SearchUserByName(name);
List<string> splitList = new List<string>();
if (lastName != null)
{
if (lastName.Count <= 10)
{
int inc = 0;
foreach(string splitter in lastName)
{
if (inc % 2 == 1)
{
splitList.Add(splitter);
}
inc++;
}
return Json(splitList, JsonRequestBehavior.AllowGet);
}
}
return null;
}
I use a splitter because another function allows me to search AD and returns several parameters (which will then be useful to immediately find a user by its unique id, that's my difficulty).
This calls the following function:
public List<string> SearchUserByName(string name)
{
try
{
DirectoryEntry ldapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(ldapConnection);
var sidInBytes=new byte[0];
//anr permet de chercher tout utilisateur contenant "name"
search.Filter = "(&(objectClass=user)(anr=" + name + "))";
//search.Filter = "(&(objectClass=User) (name=" + name + "*))";
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("distinguishedName");
resultCollection = search.FindAll();
if (resultCollection.Count == 0)
{
return null;
}
else
{
foreach(SearchResult sResult in resultCollection)
{
if (sResult.Properties["distinguishedName"][0].Equals(null) ||
sResult.Properties["displayName"][0].Equals(null))
continue;
displayName.Add(sResult.Properties["distinguishedName"][0].ToString());
displayName.Add(sResult.Properties["displayName"][0].ToString());
}
}
ldapConnection.Close();
ldapConnection.Dispose();
search.Dispose();
return displayName;
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return null;
}
Finally, when I have my list of users, I can click on their link and I load info about the user using this function:
public List<KeyValuePair<string,string>> GetUserInfoBySAMAN(string sAMAccountName)
{
try
{
DirectoryEntry ldapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(ldapConnection);
search.Filter = "(sAMAccountName=" + sAMAccountName + ")";
search.PropertiesToLoad.Add("objectSID");
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("memberOf");
search.PropertiesToLoad.Add("description");
search.PropertiesToLoad.Add("accountExpires");
search.PropertiesToLoad.Add("sAMAccountName");
result = search.FindOne();
///Conversion du SID en chaine de caractères
var sidInBytes = (byte[])result.Properties["objectSID"][0];
var sid = new SecurityIdentifier(sidInBytes, 0);
String time;
if (result.Properties["accountExpires"][0].ToString().Equals("0")|| result.Properties["accountExpires"][0].ToString().Equals("9223372036854775807"))
{
time = "Jamais";
}
else
{
///Conversion de la date en entier puis en date
DateTime dt = new DateTime(1601, 01, 02).AddTicks((Int64)result.Properties["accountExpires"][0]);
time = dt.ToString();
}
string desc="";
if (result.Properties.Contains("description"))
{
desc = result.Properties["description"][0].ToString();
}
else
{
desc = "Pas de description disponible";
}
userInfo = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("displayName",result.Properties["displayName"][0].ToString()),
new KeyValuePair<string, string>("memberOf", result.Properties["memberOf"][0].ToString()),
new KeyValuePair<string, string>("accountExpires",time),
new KeyValuePair<string, string>("description",desc),
new KeyValuePair<string, string>("sid",sid.ToString()),
new KeyValuePair<string, string>("sAMAccountName",result.Properties["sAMAccountName"][0].ToString())
/*lastName.Add(result.Properties["displayName"][0].ToString());
lastName.Add(result.Properties["memberOf"][0].ToString());
lastName.Add(sid.ToString());
lastName.Add(result.Properties["accountExpires"][0].ToString());
lastName.Add(result.Properties["description"][0].ToString());*/
};
return userInfo;
}
catch(Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return null;
}
That last function doesn't work if I change sAMAccountName by distinguishedName because apparently this attribute cannot be used like that. I want to use distinguishedName and immediately have my object.
So what I need is to search while I type, and if I select one of the proposed choices, validating the form immediately send me to user info page.
Thanks for your help, hope it is clear enough
Edit I added a 2nd script that can get the value of selected item, but I need the data passed through the controller
If I understood right, autocomplete method has select event.
$(document).ready(function () {
$("#searchName").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/SearchUserWhileTyping",
type: "GET",
data: { name: $("#searchName").val() },
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
$("#searchName").html(''),
response($.map(data, function (item) {
return {
label: item
}
}));
},
select: function(e, ui)
{
//Just Example
$.get("UserController", {ID: ui.Id}).done(
function(data){
});
//Write your ajax post or get method
//that fetches user data directly as soon as
//the item in list clicked
}
});
},
minLength: 4
})
});
Edit: I saw your edit, so that you can use your GetUserInfoBySAMAN function for ajax get request inside select event (instead where I wrote "UserController"), and you have work for binding return data to the inputs or labels as well.

Posting form data from Partial view to controller using ajax

I have a jquery grid that has a list of Employee Records.To edit the records there is a link on each row.On click of that A jquery model popup opens and loads the partial view to show and edit the data.But on click of the button(custom button not the jquery model button) on the popup(that loads a partial view),the client side validation using dataAnnotation does not work. If I make a submit form like:-
$("#btnUpdate).submit(function (e) {
e.preventDefault();
var $form = $(this);
if ($form.valid()) {
//Add ajax call
}
});
Then after submit it redirects to:- { ../Employee/Edit/EmployeeId } where it shows a blank screen as I dont have any view for this.
I want that after the form post it should just refresh the jquery grid.
public PartialViewResult _CreateSupplier()
{
return PartialView(new Supplier());
}
[HttpPost]
public JsonResult _CreateSupplier(Supplier model)
{
//Validation
return Json(new
{
status = transactionStatus,
modelState = ModelState.GetModelErorrs()
}, JsonRequestBehavior.AllowGet);
}
Form post jquery method
$('#create-supplier').submit(function (e) {
e.preventDefault();
var $form = $(this);
if (!ModelIsValid($form))
return;
AjaxPost($form.serialize(), '#Url.Action("_CreateSupplier")', function (result) {
if (result.status == 0) {
$form[0].reset();
//Success
var grid = $("#gridSupplier").data("kendoGrid");
grid.dataSource.read();
} else if (result.status == 1)
AddFormErrors($form, result);
else if (result.status == 2)
//error;
});
});
Checking model method is valid and if invalid adding errors to form
function ModelIsValid(form) {
var validator = $(form).validate(); // obtain validator
var anyError = false;
form.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
return true;
}
function AddFormErrors(form, errors) {
for (var i = 0; i < errors.modelState.length; i++) {
for (var j = 0; j < errors.modelState[i].errors.length; j++) {
var val = $(form).find("[data-valmsg-for='" + errors.modelState[i].key + "']");
if (val.html().length > 0) {
$(form).find("[for='" + errors.modelState[i].key + "']").html(errors.modelState[i].errors[j]);
} else {
val.html('<span for="' + errors.modelState[i].key + '" generated="true" class="" style="">' + errors.modelState[i].errors[j] + '</span>');
}
}
}
}
Ajax post method:
function AjaxPost(postData, url, callback) {
$.ajax({
url: url,
type: 'POST',
data: postData,
dataType: 'json',
success: function (result) {
if (callback) callback(result);
}
});
}
And last c# generic method which checks returns model state errors
public static IEnumerable<object> GetModelErorrs(this ModelStateDictionary modelState)
{
return modelState.Keys.Where(x => modelState[x].Errors.Count > 0)
.Select(x => new {
key = x,
errors = modelState[x].Errors.Select(y => y.ErrorMessage).ToArray()
});
}
Hope answer is useful...

MVC: pass parameter to action using Jquery.ajax()

I'm pretty new to MVC. I need to make ajax call to an Action with parameters using html.Action(). I'm unable to pass this..
Hope it will be helpful for other MVC begineers as well..
HTML:
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{#onclick=string.Format("return checkFleetAddedandScroing()")}) %>
Jquery:
function checkFleetAddedandScroing() {
debugger;
$.ajax({
type: "GET",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Action:
public JsonResult CheckFleetExists(Guid fleetId )
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(exists, JsonRequestBehavior.AllowGet);
}
I need to pass fleetid to action which is in Model.SelectedFleet.ID. Its being used somewhere on pages. But i'm unable to use that somehow..
please suggest where i'm doing wrong...
It looks like you are trying to invoke a controller action using AJAX when the link is clicked and depending on the result of this call either allow the user to be redirected to the actual AddRace action or be prompted with an error message.
The problem with your code is that you are attempting to return true/false from within the success AJAX callback which doesn't make any sense. You need to always return false from the click callback and inside the success callback, depending on the returned value from the server, redirect manually using the window.location.href function.
HTML:
<%: Html.ActionLink(
"Add Race",
"AddRace",
new {
eventId = Model.EventId,
fleetId = Model.SelectedFleet.ID
},
new {
data_fleetid = Model.SelectedFleet.ID,
#class = "addRace"
}
) %>
Jquery:
<script type="text/javascript">
$(function () {
$('.addRace').click(function (evt) {
$.ajax({
type: 'GET',
url: '<%= Url.Action("CheckFleetExists") %>',
cache: false,
data: { fleetId: $(this).data('fleetid') },
success: function (data) {
if (data.exists) {
// the controller action returned true => we can redirect
// to the original url:
window.location.href = url;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
}
},
error: function (req) {
}
});
// we make sure to cancel the default action of the link
// because we will be sending an AJAX call
return false;
});
});
</script>
Action:
public ActionResult CheckFleetExists(Guid fleetId)
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(new { exists = exists }, JsonRequestBehavior.AllowGet);
}
Remark: inside your AddRace controller action don't forget to perform the same verification as you are doing inside your CheckFleetExists. The user could simply disable javascript and the AJAX call will never be done.
change your action like this :
public JsonResult CheckFleetExists(string fleetId)
{
var fleetGuid = Guid.Parse(fleetId);
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetGuid );
}
catch
{
}
return new JsonResult{ Data = exists};
}
and change you ActionLink so :
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{onclick=string.Format("return checkFleetAddedandScroing({0})",Model.SelectedFleet.ID)}) %>
and your script block may look something like this :
function checkFleetAddedandScroing($fleetId) {
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
data : { "fleetId" : $fleetId },
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Problem was in answers that url to action was not complete..i did it using this way
function checkFleetAddedandScroing() {
// debugger;
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists", new {eventId=Model.EventId})%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}

Error with a getJSON call in jquery with ASP.NET MVC

I have the following code in html, I cannot get the Function call back of JSON get call. Down is the code in controller. Please Help
<script type="text/javascript">
$().ready(function() {
$("#CuitDespachante").typeWatch({ highlight: true, wait: 500, captureLength: -1, callback: finished });
});
function finished(txt) {
$.getJSON('/Documentacion/GetDatosDespachantes', { cuitDespachante: txt },
function (data) {
alert('You typed: ');
}
);
};
</script>
public ActionResult GetDatosDespachantes(string cuitDespachante)
{
cuitDespachante = cuitDespachante.Replace("-", "").Replace("_", "");
DepositarioFielWS.DepositarioFielWebService ws = new DepositarioFielWS.DepositarioFielWebService();
var res = ws.GetDespachante(cuitDespachante);
if (res.Licencia.CodigoLicencia == DepositarioFielWS.CodigoLicencia.Ok)
{
DepositarioFielWS.Despachante desp = new DepositarioFielWS.Despachante();
desp.Cuit = res.Despachante.Cuit;
desp.Nombre = res.Despachante.Nombre;
var respuesta =new
{
cuit = desp.Cuit,
nombre = desp.Nombre
};
return Json(respuesta);
}
else
{
var respuesta = new
{
cuit = cuitDespachante,
nombre = "Imposible Realizar Consulta"
};
return Json(respuesta);
}
}
I have to add this in the response of the controller, Something new in ASP.NET MVC 2
return Json(respuesta,JsonRequestBehavior.AllowGet);

Resources