How to check Unique attribute in mvc 3? - asp.net-mvc

I have a textbox for username in a form, when user enter the username, i need to check if that username is already in data base. I'm thinking to catch the blur event of the text box & to write a javascript function to query & check in database. I'm trying some thing like this:
#html.textboxfor(x=>x.UserName, new{#id="UserName"})
<script type="text/javascript">
$(document).ready(function(){$('#UserName').blur("then some code here");})
</script>
Now I need to know if I'm following the right way? If so then please let me know how can I call a action method which will interact with the database within the blur function or whats the right way? Thanks in advance.

Yes, that looks right. You can use a JQuery Ajax call, along with the Url.Action helper method.
$(document).ready(function(){
$('#UserName').blur(function() {
var name = this.value;
$.get(#Url.Action("VerifyUsername") + "?name=" + value, function(result) {
if (result.ok == false) {
$("#message").text("Username '" + name + "' is already taken, please try another");
}
});
});
});
This will call an action VerifyUsername in the current controller. It assumes that the action returns JSON like {ok:true} to verify the name:
public ActionResult VerifyUsername(string name)
{
bool isOk;
// check the database
return new JsonResult() {
Data = new { ok: isOk },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

you can use remote validation in MVC3
http://msdn.microsoft.com/en-us/library/gg508808(v=vs.98).aspx

Related

MVC 4 #HTML.DropdownlistFor onchange event needs to send SelectedIndex value

I am using MVC 4 and have an #HTML.DropdownlistFor() which loads the rest of the page based on it's selection. On change of the listbox, I want to reload the page so that it load the correct data. As well there are two other parameters that are needed to load the page correctly.
In Create.cshtml view
#Html.DropDownListFor(model => model.SelectedMissionID, Model.MissionsToDisplay, new { onchange = "ReloadPage();" })
function ReloadPage() {
window.location = '#Html.Raw(Url.Action("CreateEdit", "DailyLog", new { ID = 1, ID2 = 0, dailyLogDate = Model.LogDate }))';
}
Where it says ID = 1, I want the selected index of the DropdownlistFor(SelectedMissionID), how do I get this?
I'm not sure if this is the best way to go to the controller, or if I should use a JQUERY .ajax post, is there a better way?
I seems something ideal for an ajax post.
What you have done is OK, inside the ReloadPage() function, just get the selected value in the DropDown, do the Ajax call passing the parameters, and in the success callback put your returned HTML in some container.
The idea is that you replace a part of your view with the return of your Ajax call, not all the page.
To get the selected value, using jQuery:
var selectedValue = $("select[name='SelectedMissionID']").val();
And that can be placed in your ReloadPage() function.
$.post( "your action URL", { ID: selectedValue, OtherParam: "xxxxx" })
.done(function( data ) {
alert( "Data Loaded: " + data );
//here you need to get the HTML, and put in a container
});

MVC Dynamically append img tag from controller

I want to add unknown number of images based on how many is there for specific user; i have used .Append function for div,labels,inputs and its work fine but when i want to append with source its not working !
so how can i do this ?
i have tried this:
` string sc = "$('<img/>', {src=\"~/Content/themes/img2.jpg\" alt=\"\",class:'table-wrapper'}).appendTo(finalDalata);";
return JavaScript(sc)`
finalDalata is my Div name
so whats iam doing wrong ?
Your appendTo code is invalid, it needs a selector, and your image attributes are not formatted properly, so it should be:
string sc = "$('<img/>', { src:'~/Content/themes/img2.jpg', alt:'', class:'table-wrapper'}).appendTo('#finalDalata');"
However, controller should return data and not control (exploits and injections comes to mind), so a better way would be to create an AppendImage function on the View side in javascript:
function AppendImage(attributes)
{
$('<img/>', attributes).appendTo('#finalDalata');
}
Note: you should probably sanitize the attributes before to be sure.
Then return a list of attributes only:
var images = new List<dynamic>();
// Do this for each images
images.Add(new { src="~/Content/themes/img2.jpg", alt="", class="table-wrapper"});
return Json(images);
And in the ajax success you can:
success: function (data) {
data.foreach( function (item) {
AppendImage(item);
});
}
Solved by TagBuilder
TagBuilder tag = new TagBuilder("img");
tag.Attributes.Add("id", "myImage");
tag.Attributes.Add("src", "/imgs/" + UserName + ".jpg");
tag.Attributes.Add("alt", "my image");
tag.Attributes.Add("class", "imgsClass");
then convert tag to string and pass it back to view
thnx

Is it possible that MVC is caching my data some place?

I have the following controller action:
public ActionResult Details(string pk)
{
IEnumerable<ContentDetail> model = null;
try
{
model = _content.Details(pk);
if (model.Count() > 0)
{
return PartialView(getView(pk) + "Details", model);
}
}
catch (Exception e)
{
log(e);
}
return Content("No records found");
}
I call this with the following routine:
$.ajax({
cache: false,
url: "/Administration/" + table + "s/Details",
data: { pk: partitionKey },
dataType: 'html',
success: function (responseText) {
$('#detailData').html(responseText);
$(".updatable")
.change(function (e) {
var type = $(this).attr('id').split('_')[0];
updateField(table, $(this), type);
});
$('.dialogLink')
.click(function () {
dialogClick(this);
return false;
});
},
error: function (ajaxContext) {
ajaxOnFailure(ajaxContext)
}
});
What I notice is that sometimes when I put a break point on the first line of the controller action then it does not seem to stop at the breakpoint. Is it possible the results are being cached by MVC and how could I stop this from happening while I debug?
Check for any variation of OutputCache being set on the controller itself or, if present, a base controller all your controllers may inherit from.
I've also noticed IE likes to cache things and found the only way to alleviate this is doing to the developer window and clearing the cache (or ctrl+shift+del)
Try adding cache:false to your .ajax call and see if that has any bearing (jQuery will append a timestamp variable making each call unique). Nevermind, just noticed you have it included. Must be getting late here--sure sign it's bed time when I miss things like this.
Load up fiddler and see if the request is even coming back from the browser. Ideally you'll want I write out no cache headers through one of the many methods mentioned here
Disable browser cache for entire ASP.NET website

What is the proper way to do multi-parameter AJAX form validation with jQuery and ASP.NET MVC?

I have a registration form for a website that needs to check if an email address already exists for a given company id. When the user tabs or clicks out of the email field (blur event), I want jQuery to go off and do an AJAX request so I can then warn the user they need to pick another address.
In my controller, I have a method such as this:
public JsonResult IsEmailValid(int companyId, string customerNumber)
{
return Json(...);
}
To make this work, I will need to update my routes to point directly to /Home/IsEmailValid and the two parameters {companyId} and {customerNumber}. This seems like I'm "hacking" around in the routing system and I'm guessing perhaps there is a cleaner alternative.
Is there a "proper" or recommended way to accomplish this task?
EDIT: What I meant by the routes is that passing in extra parameter ({customerNumber}) in the URL (/Home/IsEmailValid/{companyId}/{customerNumber}) won't work with the default route mapping.
You can use the jQuery Validation Plugin to do that.
You're gonna have to implement your own method though like this :
$.validator.addMethod("checkCompanyEmail", function(value, element) {
var email = value;
var companyID = //get the companyID
var result;
//post the data to server side and process the result and return it
return result;
}, "That company email is already taken.");
Then register your validation method :
$("#the-form").validate({
rules: { email: { required: true, "checkCompanyEmail" : true } }
});
PS. I don't understand why you need to "hack around" with routing for that.
from the validate documentation under remote method
remote: {
url: "check-email.php",
type: "post",
data: {
username: function() {
return $("#username").val();
}
}
}

Can I pass a parameter with the OnSuccess event in a Ajax.ActionLink

When I use:
new AjaxOptions
{
UpdateTargetId = "VoteCount" + indx,
OnSuccess = "AnimateVoteMessage"
}
everything works fine...but I am trying to animate items in a list, with automatically assigned ID's. Since I want each of these to be addressable from my javascript, I believe I need to pass a parameter to my javascript. But when I use:
new AjaxOptions
{
UpdateTargetId = "VoteCount" + indx,
OnSuccess = "AnimateVoteMessage(2)"
}
I get an " Sys.ArgumentUndefinedException: Value cannot be undefined." exception. Well I get that when using the debug versions of MicrosoftMvcAjax.js. When using the compressed version I get a "Microsoft JScript runtime error: 'b' is null or not an object"
So my question is, can I pass a parameter to my javascript function using the OnSuccess event for a ActionLink?
Is this the right approach? How else am I going to have one javascript function have the ability to be run on 10 items (in my case the IDs of multiple DIVs) on my page?
There is a better way to do this - use the built in parameters that the OnSuccess call can be expected to pass
the built in parameters (the ones I found so far anyway) are data, status and xhr
data = whatever you return from the action method
status = if successful this status is just a string that says "success"
xhr = object that points to a bunch of javascript stuff that I will not be discussing...
so you would define your javascript like this (you can leave out the arguments you don't need - since all we want is our data back from the action we will just take the data argument)
function myOnSuccessFunction (data)
{
..do stuff here with the passed in data...
}
like I said before, data is whatever JSON that may be returned by the ActionResult so if your controller action method looks like this...
public ActionResult MyServerAction(Guid modelId)
{
MyModel mod = new MyModel(modelId);
mod.DoStuff();
return Json(mod, JsonRequestBehavior.AllowGet);
}
you would set up your action link like this...
#Ajax.ActionLink("Do Stuff", "MyServerAction", new { modelId = Model.Id }, new AjaxOptions { OnSuccess = "mySuccessScript(data);", OnFailure = "myFailureScript();", Confirm = "Are you sure you want to do stuff on the server?" })
this will create a confirmation message box asking if you want to actually invoke the action - clicking yes on the prompt will invoke the call to the controller - when the call comes back - the data argument will contain a JSON object of whatever you returned in your action method. Easy Peasy!
But wait! What if I want to pass another custom argument?! Simple! Just add your arguments to the front of the list...
instead of this...
function myOnSuccessFunction (data)
{
..do stuff here with the passed in data...
}
do this (you can have more than one custom argument if you like, just keep adding them as needed)...
function myOnSuccessFunction (myCustomArg, data)
{
..do stuff here with the passed in data and custom args...
}
then in your setup - just get the argument through some client side script within your ActionLink definition... i.e.
#Ajax.ActionLink("DoStuff", "MyServerAction", new { modelId = Model.Id }, new AjaxOptions { OnSuccess = "mySuccessScript(myClientSideArg, data);", OnFailure = "myFailureScript();", Confirm = "Are you sure you want to do stuff on the server?" })
Note that "myClientSideArg" in the OnSuccess parameter can come from wherever you need it to - just replace this text with what you need.
Hope That Helps!
or...a bit different syntax that worked for me:
OnSuccess = "( function() { MyFunction(arg1,arg2); } )"
There is a better way, which I believe is how Microsoft intended it: Set the AjaxOptions.OnSuccess to a function pointer, i.e. just the name of the function, no parameters. MVC will send it parameters automagically. Below is an example.
JScript parameter:
public class ObjectForJScript
{
List<int> Ids { get; set; }
}
Jscript function:
function onFormSuccess(foobar){
alert(foobar);
alert(foobar.Ids);
alert(foobar.Ids[0]);
}
View code:
#using (Ajax.BeginForm("ControllerAction", "ControllerName",
new AjaxOptions
{
OnSuccess = "onFormSuccess" //see, just the name of our function
}))
{
#Html.Hidden("test", 2)
}
Controller code:
public JsonResult ControllerAction(int test)
{
var returnObject = new ObjectForJScript
{
Ids = new List<int>{test}
};
return Json(returnObject);
}
Note that the parameter name in the JScript function doesn't matter, you don't have to call it "returnObject" even though the controller names it so.
Also note that Json() conveniently turns our List into a JScript array. As long as the methods of the C# object are translatable to Json, you can call them in the JScript like I've done.
Finally, the controller doesn't have to return a JsonResult, it can be ActionResult (but it's usually better to have a controller action do just one thing).
The above example will alert two objects (the Json and the array object which it contains), and then 2.
You can simply do this
Razor:
... OnSuccess = "AnimateVoteMessage('" + YourParameter + "')"
Please note the single quotes!
JavaScript:
function AnimateVoteMessage(YourParameter){
alert(YourParameter);
}
Enjoy,
Try this - it works for me:
OnSuccess = "new Function('MyFunction(" + myParameter + ")')"
Use this:
OnSuccess = "function(){yourfunction(" + productcode + ");}"
or
OnSuccess = "function(){yourfunction(this, " + productcode + ");}"
I ran in this issue too... and did not find a way to solve it!
I did a workaround (which is not nice but solved it for now... maybe until someone posts a solution here)...
what I did was place a hidden field in the TargetId div and OnSuccess I called a js method which retrieves the value from the hidden field <- this could happen in your AnimateVoteMessage method ...
See http://www.codeproject.com/KB/ajax/Parameters-OnSuccess.aspx
Basically:
function yourCallBack(arg1,arg2) {
return function(result) { // Your old function
alert(arg1); // param will be accessible here
alert(arg2); // param will be accessible here
alert(result);// result = the response returned from Ajax
}
}
Simply, at AjaxOptions, use the following:
OnSuccess = "onSuccessFunction(data, 'Arg1');"
Then at your function, you will get the new value as:
function onSuccessFunction(result, myNewArg) {
//Prints Arg1
Console.Write(myNewArg)
}

Resources