I have controller : RecruitmentController.cs
and i have method/action : cekrecomended
public string cekrecomended(string id)
{
id = EncryptDecrypt.Decrypt(id);
string ada = "false";
string jurusan = Session["Jurusan"].ToString();
string pendidikan = Session["Pendidikan"].ToString();
int usia = Convert.ToInt16(Session["Usia"]);
string kelamin = Session["Kelamin"].ToString();
double nilai = Convert.ToDouble(Session["Nilai"]);
var data = (from c in db.ViewVacancyJabatanPerusahaans
where
c.Pendidikan.Contains(pendidikan) &&
(c.Jurusan.Contains(jurusan) || c.Jurusan.Contains("Semua jurusan")) &&
c.Nilai <= nilai &&
c.UsiaDari <= usia &&
c.UsiaSampai >= usia &&
c.JenisKelamin.Contains(kelamin) &&
c.TglAkhirlamaran >= DateTime.Now &&
c.Dlt == false &&
c.IDVancancy == Convert.ToInt16(id)
orderby c.IDVancancy descending
select c).Count();
if (data > 0)
{
ada = "true";
}
return ada;
}
i want to access cekrecomended from view.
#if(Human_Resource_Development.Controllers.RecruitmentController.cekrecomended(Convert.ToString(item.IDVancancy)) == "true")
{
<button>Apply this position</button>
}
but i get error.
This defeats the separation of model, view and controller MVC is based on - in your view you should just use your view model. In your case just use a view model that has a property making the result of this method call available.
You should use your view model for that purpose. Let's say MyViewModel is the class of your model, add a boolean property named IsRecommended
public class MyViewModel
{
// all of the other properties
// ....
public bool IsRecommended { get; set; }
}
Set the value of IsRecommended in your controller action method
public ActionResult Index()
{
MyViewModel model = new MyViewModel();
// other codes here
// ...
model.IsRecommended = ....; // logic from cekrecomended method here
return View(model);
}
Make sure you have this syntax at the top of your view
#model MyViewModel
and determine whether the "Apply this position" button will be displayed or not based on the value of IsRecommended property as below
#if (Model.IsRecommended)
{
<button>Apply this position</button>
}
Thank you for your answers. My problem solved, i have solution.
i just change
public string cekrecomended(string id)
{
//bla bla
}
to
public static string cekrecomended(string id)
{
//bla bla
}
and i can access from view.
I have a form that once submitted will have some complex routing based on what is entered in combination with server side calculaitons. I want to pass data that is collected from the first form to second form via RedirectToAction.
At first I thought I could perform a RedirectToAction to pass the data via a POST method cleanly, but it appears there is no easy way to do this. Reading more I want to see if there is some easy way I can just pass a Hashtable or ViewData through an RedirectToAction to the proper ActionResult and just read the variables but that is proving more challenging than I thought.
Here is a simplified version of what I am trying it.
[AcceptVerbs("GET","POST")]
public ActionResult Step8(int id = 0, Hashtable FormValues = null) {
// was this a redirect back to us?
if (FormValues != null && FormValues.Count > 0) {
if (FormValues.ContainsKey("title") && FormValues["title"] != null) {
string _title = FormValues["title"].ToString();
}
}
// the form in thie view redirects to Step9
return View();
}
[AcceptVerbs("POST")]
public ActionResult Step9(int id = 0) {
bool issue_found = true;
if(issue_found){
// hypothetical issue found, back to previous step
Hashtable _FormValues = new Hashtable();
_FormValues.Add("title", "My Title");
_FormValues.Add("product", "My thing");
return this.RedirectToAction("Step8", _FormValues);
}else{
// .. do stuff
return View();
}
}
What am I doing wrong? How can I pass this data?
The approach was more complicated then it needed to be. TempData survives a Redirect so that is what I did. Here is a working solution:
[AcceptVerbs("GET","POST")]
public ActionResult Step8(int id = 0) {
string _product = "";
string _title = "";
// was this a redirect back to us?
try {
if (TempData != null) {
if (TempData.ContainsKey("product") && TempData["product"] != null) {
_product = TempData["product"].ToString();
}
if (TempData.ContainsKey("title") && TempData["title"] != null) {
_title = TempData["title"].ToString();
}
}
} catch {}
// The form in this view performs a POST to Step9
return View();
}
[AcceptVerbs("POST")]
public ActionResult Step9(int id = 0) {
bool issue_found = true;
if(issue_found){
// hypothetical issue found, back to previous step
TempData["title"] = "My Title";
TempData["product"] = "My thing";
return this.RedirectToAction("Step8");
}else{
// .. do stuff
return View();
}
}
I have a model that (among other things) returns a tabular representation of itself when a method - ToHtml() - is called.
LotSpace and LotRow are both models that (for brevity) I am not including. They actually make database calls, and are the reason I would like to redraw this lot using ajax calls. If they are relevant to this question I can add them.
public class Lot
{
public List<LotSpace> Spaces;
public List<LotRow> Rows;
public int SpacesPerRow
{
get
{
return (Spaces.Count / Rows.Count);
}
}
public Lot(int startSpace, int endSpace, int numberOfRows)
{
Spaces = LotSpace.ToList(startSpace, endSpace);
/***testing*****/
Spaces[0].Blocked = true;
Spaces[1].Blocked = true;
Spaces[2].Blocked = true;
Spaces[3].Blocked = true;
Spaces[4].Blocked = true;
Spaces[5].Blocked = true;
Spaces[6].Blocked = true;
Spaces[7].Blocked = true;
/***testing*****/
Rows = LotRow.ToList(numberOfRows);
LoadSpacesIntoRows();
}
private void LoadSpacesIntoRows()
{
foreach(var space in Spaces)
{
int rowIndex = 0;
while(rowIndex < Rows.Count)
{
if(Rows[rowIndex].Spaces.Count < SpacesPerRow)
{
Rows[rowIndex].Spaces.Add(space);
break;
}
rowIndex++;
}
}
}
public string ToHtml()
{
Table table = MapMaker.HTML.CreateTable(this);
MapMaker.HTML.AddSpaces(table, this);
return MapMaker.HTML.ControlToString(table);
}
}
Right now this is called from the view like this:
Controller
public ActionResult Index()
{
return View(new Lot(392, 1, 7));
}
View
<div class="row">
#Html.Raw(Model.ToHtml())
</div>
This works, but under certain circumstances, I would like to be able to redraw this map. Is it possible to make an ajax call from the view so that I can redraw this portion of the view on demand without necessitating a full page reload?
Yes. But AJAX doesn't "call a method on a model", it invokes a controller action. So, for example, you can create a new controller action with a new view which returns only that HTML:
public ActionResult Lot()
{
return View(new Lot(392, 1, 7));
}
And, aside from the #model declaration, the view would just be:
#Html.Raw(Model.ToHtml())
Now you have a URL which returns just the HTML for that table and nothing else. You can fetch it using something like the jQuery load() function:
$('#yourDiv').load('#Url.Action("Lot", "YourController")');
The AJAX request is a standard HTTP request like any other. You just need an endpoint on the server to handle that request and return a response.
I would like to return an image that is dynamically created instead of retrieving from a database or from file. Let's say I have a simple ZipCode class. I would like to have a property that would return an image representation of the zipcode. The JSON returns "ZipAsImage":"System.Drawing.Bitmap".
Yes I am new to the programming in the web world. Yes I have looked for other examples but they seemed to only return an image. Thanks for any help.
public class ZipCode
{
public int ZipCodeId { get; set; }
[NotMapped]
public Image ZipAsImage
{
get
{
// Create a blank iamge for now to test.
return new Bitmap(50, 50);
}
set { }
}
}
My ApiController class
public class ZipCodesController : ApiController
{
private MyContext db = new MyContext();
// GET api/ZipCodesController
public IEnumerable<ZipCode> GetZipCodes()
{
return db.zipcodes.AsEnumerable();
}
// GET api/ZipCodesController/5
public ZipCode GetZipCode(int id)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return zipcode;
}
...
My Controller class
public class ZipCodesController : Controller
{
private MyContext db = new MyContext();
//
// GET: /ZipCodes/
public ActionResult Index()
{
var zipcodes = db.ZipCodes.Include(z => z.State);
return View(zipcodes.ToList());
}
//
// GET: /ZipCodes/Details/5
public ActionResult Details(int id = 0)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
return HttpNotFound();
}
return View(zipcode);
}
...
I dont undersatnd the point where you are showing the MVC Contoller.Am i missing something there? However For Webapi (ApiController) You can re write your Method as follows. This should pass the enitre Object in one response.
public HttpResponseMessage GetZipCode(int id)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound)
}
return Request.CreateResponse(HttpStatusCode.OK,zipcode);
}
Sending Binary Images. You need to set Straemcontent and content-type. I found a link that can help you with that Images with Webapi . Look through the entire thread . You might figure out quickly whats missing...
In my viewmodel, I have a list of items I fetch from the database and then send to the view. I would like to know if it's possible to avoid having to refill the options property whenever I hit a Post action and need to return the model (for validation errors and what not)?
In webforms, this wouldn't be necessary.
Edit: I was not clear. My problem is with the SelectList options I use for my DropDownLists. Everything gets posted, but if I have to return to the view (model is invalid), I have to reload the options from the database! I want to know if this can be avoided.
My viewmodel:
public class TestModel
{
public TestModel()
{
Departments = new List<SelectListItem>();
}
public string Name { get; set; }
public int Department { get; set; }
public IEnumerable<SelectListItem> Departments { get; set; }
}
My view:
#model MvcApplication1.Models.TestModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.Name)
#Html.DropDownListFor(m => m.Department, Model.Departments)
<input type=submit value=Submit />
}
My controller (do notice the comment on HttpPost):
public ActionResult Index()
{
TestModel model = new TestModel
{
Name = "Rafael",
Department = 1,
Departments = new List<SelectListItem>
{
new SelectListItem { Text = "Sales", Value = "1" },
new SelectListItem { Text = "Marketing", Value = "2", Selected = true },
new SelectListItem { Text = "Development", Value = "3" }
}
};
// Departments gets filled from a database.
return View(model);
}
[HttpPost]
public ActionResult Index(TestModel model)
{
if (!ModelState.IsValid)
{
//Do I have to fill model.Departments again!?!?!?
return View(model);
}
else { ... }
}
Thanks in advance.
Edit: FYI, my solution was to use the Session variable.
Just need to strongly type your view, and change your controller method to have a parameter of that class type.
That is, the view
#model MyNamesspace.Models.MyModel
...
#using (Html.BeginForm())
{
....
}
And you controller method which is posted to.
[HttpPost]
public ActionResult MyAction(MyModel model)
{
...
}
EDIT: Also make sure you have form fields for each property of the model which you need posted to the controller. My example is using Razor too BTW.
I encountered a similar problem when trying to create an Order wizard in MVC (one where each page of the wizard is implemented as a partial view loaded by AJAX). I highly doubt it is the suggested method but my way of solving this was to call a custom MergeChanges method in each action called by my wizard:
public Order MergeChanges(Order newOrder)
{
var sessionHistory = (List<string>)Session["sessionHistory"];
if (sessionHistory == null || sessionHistory.Count == 0)
return MergeChanges(newOrder, -1);
return MergeChanges(newOrder, MasterViewController.GetStepNumberByName(sessionHistory.Last()));
}
public Order MergeChanges(Order newOrder, int step)
{
PreMerge(newOrder);
Order result = null;
try
{
ApplyLookups(ref newOrder);
Order oldOrder = (Order)Session["order"];
if (oldOrder == null)
{
Session["order"] = newOrder;
result = newOrder;
}
else
{
List<TypeHelper.DecoratedProperty<ModelPageAttribute>> props = null;
newOrder.GetType().GetDecoratedProperty<ModelPageAttribute>(ref props);
props = props.Where(p => (p.Attributes.Count() > 0 && p.Attributes.First().PageNumber.Contains(step))).ToList();
foreach (var propPair in props)
{
object oldObj = oldOrder;
object newObj = newOrder;
if (!string.IsNullOrEmpty(propPair.PropertyPath))
{
bool badProp = false;
foreach (string propStr in propPair.PropertyPath.Split('\\'))
{
var prop = oldObj.GetType().GetProperty(propStr);
if (prop == null)
{
badProp = true;
break;
}
oldObj = prop.GetValue(oldObj, BindingFlags.GetProperty, null, null, null);
newObj = prop.GetValue(newObj, BindingFlags.GetProperty, null, null, null);
}
if (badProp)
continue;
}
if (newObj == null)
continue;
var srcVal = propPair.Property.GetValue(newObj, BindingFlags.GetProperty, null, null, null);
var dstVal = propPair.Property.GetValue(oldObj, BindingFlags.GetProperty, null, null, null);
var mergeHelperAttr = propPair.Property.GetAttribute<MergeHelperAttribute>();
if (mergeHelperAttr == null)
{
if (newObj != null)
propPair.Property.SetValue(oldObj, srcVal, BindingFlags.SetProperty, null, null, null);
}
else
{
var mergeHelper = (IMergeHelper)Activator.CreateInstance(mergeHelperAttr.HelperType);
if (mergeHelper == null)
continue;
mergeHelper.Merge(context, HttpContext.Request, newObj, propPair.Property, srcVal, oldObj, propPair.Property, dstVal);
}
}
result = oldOrder;
}
}
finally
{
PostMerge(result);
}
return result;
}
Since my case was doing this with a wizard, only specific values applied to each page so in order to only account for properties known to the current page of the wizard, I've implemented some attributes, a (admittedly over complex) ViewController layer, and a custom validation layer. I can share some more code but the code above does the grunt work if you aren't in such a complex situation. If there is a better way, I hope to learn it from the answers to this question because this was a PITA.
I am surprised this question doesn't come up more often, and I am also surprised the obvious (IMHO) answer isn't standard practice these days: nearly all POSTs should be Ajax-based. This solves a whole slew of problems including
No need to repopulate form data when you have e.g. a validation error, or application error (exception). This is particularly desirable when you have client-side state (in true rich web application fashion).
No compulsion to perform client-side validation. Validation can be 100% server-side (where it must be anyways) and the user experience is nearly the same.
Of course, there is some initial work you need to do to build out a framework for this, for example, I have a set of AjaxUpdate, AjaxNothing, AjaxRedirect, AjaxErrors ... ActionResult types which render Json which is processed by some custom Javascript. But once you get that in place, it's smooth sailing.