ASP.NET MVC: Caching combobox - asp.net-mvc

Is it possible to cash drop down list?
I'm using a Telerik MVC Window, ComboBox, and the contents of the window (including ComboBox) is being returned with a partial view. Contents of the partial view depends on the list of parameters, but on the every div in this window there is a combo box contents of which is usually unchanged and it contains ~2000 records.
i'm thinking about returning ViewData["ComboContent"] using separate controller with cashing before returning the window itself, but may be there is a better way...
TIA
updated (my controller code):
[AcceptVerbs("GET")]
[OutputCache(Duration = int.MaxValue, VaryByParam = "id")] //Some custom param??
public ActionResult LoadTimeOffset(int id)
{
String error;
IEnumerable<MyModel> model = repo.GetSomeVariableStuff(id, 10, out error); //always varies
ViewData["ComboList"] = new SelectList(repo.GetComboitems(id), "Key", "Value", -1); //changes only on id
if (model.Count() > 0)
{
return PartialView("Partial", model);
}
return Content(error);
}

Cache the data instead of caching the drop-down.
So, instead of putting the SelectList into the ViewData, put the contents for it:
if (HttpContext.Current.Cache["ComboList"] == null)
{
HttpContext.Current.Cache["ComboList"] = repo.GetComboitems(id); //use Add instead so that you can specify the cache duration.
}
ViewData["ComboList"] = HttpContext.Current.Cache["ComboList"]; //take from cache.
Note, code is not accurate, but it is an example only.
Then, in your view, render the combo.
I hope this helps.

Related

Partial View Result

Can I return a view in PartialViewResult() like the following?:
public PartialViewResult EditAdminProfile_Post(int Id, FormCollection formCollection)
{
//if (Session["AdminID"] != null)
//{
Admin admin = new Admin();
admin = db.Admins.Single(m => m.ID == Id);
admin.Name = formCollection[0];
admin.Gender = formCollection[1];
admin.Email = formCollection[2];
admin.ContactNumber = formCollection[3];
admin.AboutMe = formCollection[4];
if (ModelState.IsValid)
{
db.Entry(admin).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
}
return PartialView("AdminProfile");
AdminProfile is not a partial view.
Yes you can. It's not advised though, since your _layout is ignored (which means css or script files defined in the layout, so your styles and functionality may behave differently as you'd expect). Even though you can make it work, you're looking at code smell.
Are you looking to reuse AdminProfile as both a partial and normal view?
Create a partial view AdminProfilePartial with reusable content.
In your AdminProfile view, call AdminProfilePartial inside it (even if that's all you use)
Then when you return the full view:
return View("AdminProfile");
Otherwise partial view:
return PartialView("AdminProfilePartial");
The problem is that you don't pass the model to you partial view, that's why when you call it you get a Null reference
Update your code with this line:
return PartialView("AdminProfile", admin);
PS Instead of using FormCollection it's better to use default model binder and accept the Admin model in your action method

Select from a list passed to view in .NET MVC

Before I had this:
public ActionResult ShowSong(int id)
{
return view(db.PublishedSongs.Where(x => x.Id == id).FirstOrDefault());
}
and in my view:
#model MusicSite.Models.PublishedSong
<h2>#Model.SongName</h2>
#Html.ImageFor(x => x.CoverImageBytes, #Model.SongName + " Image", new { #class = "big-cover-image" })
This worked fine for just retrieving one item from DB and showing on view.
However now, I need to also pass a list to my view, because I want to show all of the items in model and just the select item that was passed through action method, how do I do this?
If I pass return View(db.PublishedSongs); to view then I no longer know which id to get to show just that one item.
As I am not that much good in .NET MVC but I will try to answer according to spring MVC knowledge.
The rough idea is to pass list to view as you are mentioned and along with it pass the id that you want to select using ViewBag. Now in view iterate over the list, while iteration check whether id come from iteration is equal to id that you passed in ViewBag.
So in controller :
public ActionResult ShowSong(int id)
{
ViewBag.SelectId = id;
return view(db.PublishedSongs);
}
In View :
(Loop over the db.PublishedSongs)
{
if(PublishedSong.id=#ViewBag.SelectId)
{
//select current PublishedSong
}
else
{
//otherwise
}
}

Avoid to show Null or specific values to razor view engine

I am working on asp.net mvc3 web application using MS Sql server 2008 express rc2. In my app I have two different brands in DB and one of them have few Null or 'unknown' values (e.g. 'unknown' is added to DB instead of Null). My question is how to pass only non null values to View Engine instead of using If/Else statements in View?
in controller:
var model = _data.GetViewModel(query);
if (model != null)
{
return View(model);
}
else
return View("Error");
in ViewModel;
public int Id { get; set; }
public string Query { get; set; }
public string Brand { get; set; }
public string Family { get; set; }
public string Type { get; set; }
in Model:
public ViewModel GetViewModel(string query)
{
var data = _comp.Get(p => p.Query == query);
if (data == null) return null;
return new ViewModel
{
Id = data.id,
Brand = data.brand,
Family = data.family,
Type = data.type
};
}
in View (I am currently using If statement):
#if (Model.Brand != null)
{
<span class="brand">#Model.Brand</span>
}
#if (Model.Family != null)
{
<span class="family">#Model.Family</span>
}
#if (Model.Type != null)
{
<span class="type">#Model.Type</span>
}
Note: I want to avoid If statement because there are too many values in the Database of each brand, and many of the them are Null, So I don't want to generate Html for those Null values. I am using If/Else statement like above code, and for checking too many values in View using If, it costs Memory on server and processor, and it also slow down server response time.
I want to have an alternative method to do this. Should I use Partial views or anything else?
Please Please help me to solve this, Your help is very appreciated.
Thanks and Regards.
First, some background/context, then my suggestion.
(By the way, this all applies to any version of ASP.NET MVC or ASP.NET NancyFX (yes, there's another option out there!!), etc)
Context / Background
To solve this, people generally fall into two types of categories:
Just get data and let the View decide what to show (common one, not the proper way IMO).
The Controller should handle all the heavy lifting and give the view the exact answer (proper way, IMO).
The first way is quick and dirty. Sure it works, but it puts too much logic into the view. Views are not supposed to do any logic at all (exception: for loops, and maybe the odd if/else, maybe). The main reason for this is testing. Yep, that dirty word which people hate and think it's for hippies only. Or .. I don't have the time to test.. so I manually test, etc.. If you put any business logic into a view, you cannot test that.
The second way might seem a bit slower at first, but that's like anything - the more you practice, the faster you go. This is (IMO) the preferred method of doing things because you can test the controller. The controller should create a view model which will have -the exact- results that the view needs. Not extra. For example, imagine you want to return a list of Brands to the display/view. Most people do (the equivalent of) Get-all-brands into a list, and send that list to the view, even though 80% of those properties are -not- going to be used by that view! Even if ONE property is not going to be used by that view, do not retrieve it nor send it to the view!
So - TL;DR; do all the heavy lifting in the controller. The View is dumb. Just dump the exact view model data, to the view.
Solution to your problem
Ok, so let's roll with idea #2 and get all this stuff happening in the controller.
// Grab the results.
// ASSUMPTION: It is only returning the -exact- data I need. No more, no less.
var results = _data.GetViewModel(query);
if (model == null)
{
// Project the results into a perfectly tight & svelte view model
// 100% specific for this view.
var viewModel = results.
Select(x => new ViewModel
{
Id = x.Id,
Brand = string.IsNullOrEmpty(x.Brand)
? string.Empty
: x.Brand,
Family = string.IsNullOrEmpty(x.Family)
? string.Empty
: x.Family,
Type = string.IsNullOrEmpty(x.Type)
? string.Empty
: x.Type,
}).ToList();
return viewModel;
Testing this..
[Fact]
public void GivenSomeBrands_Index_ReturnsAViewModel()
{
// Arrange.
// NOTE: Our fake repostitory has some fake data. In it ..
// Id: 1, Brand: Gucci.
// Id: 22, Brand: null.
var controller = new BrandController(SomeFakeRepositoryThingy);
// Act.
var result = controller.Index(); // This calls that controller code, above.
// Assert.
Assert.IsNotNull(result); // Controller returned some result.
Assert.IsNotNull(result.Model); // We have some model data.
var model = result.Model as IList<ViewModel>(); // Cast the Model value.
Assert.NotNull(model); // We have a strongly typed view model.
// We check the first brand value.
Assert.Equal("Gucci", model.First().Brand);
// We know this item has a null Brand,
Assert.Equal(string.Empty, model[21].Brand); but the ViewModel converted it.
}
You could write a custom HTML helper:
public static string MyHelper<V>(this HtmlHelper helper, V value, string css)
{
if (value == null)
return "";
return String.Format("<span class='{0}'>{1}</span>", value, css);
}
Then in your view:
#Html.MyHelper(Model.Brand, "brand");
#Html.MyHelper(Model.Family, "family");
#Html.MyHelper(Model.Type, "type");

Insertion on Asp.Net Mvc Failed

On my asp.net mvc project, the table data will be displayed on a grid view using Index Method.
After doing Insertion, it would redirect to Index using RedirectToAction. But for the First time, the new row is getting added to the grid. When tried second time, the insertion is not possible.
But if i reload the page using browser reload again, for the first time only insertion takes place. Please help me to resolve this issue.
When I tried to debug, "the process has been changed since the last step" takes place. So, the values during the first debug also coming for insertion on second time which break the operation. Give Solution pls..
public ActionResult Index()
{
X_DEVEntities Entity = new X_DEVEntities();
var outPut=Entity.Model.ToList();
return View(outPut);
}
public ActionResult Insert(Model modelData)
{
X_DEVEntities Entity = new X_DEVEntities();
modelData.create_user_id = "ty";
modelData.last_mod_dtm = DateTime.Now;
modelData.last_mod_user_id = "gdf";
Entity.Model.Add(modelData);
Entity.SaveChanges();
return RedirectToAction("Index");
}
On second insertion you are getting error because on each insertion you'll have same create_user_id and last_mod_user_id based upon the your Insert method you posted.
I'm guessing it should be something like this
public ActionResult Insert(Model modelData)
{
X_DEVEntities Entity = new X_DEVEntities();//try not to do this in your Insert method, rather have a constructer where you place this instantiation.
Entity.yourTableName.UserId=modelData.create_user_id;//(UserId should be the field where you want to place the username you get from the view)
modelData.last_mod_dtm = DateTime.Now;
Entity.yourTableName.LastModUserId=modelData.last_mod_user_id;//again LastModUserId is the field where you want to save your modelData.last_mod_user_id in table.
Entity.Model.Add(modelData);
Entity.SaveChanges();
return RedirectToAction("Index");
}

Why does creating a new ViewModel return the same data as the old ViewModel?

I'm just learning MVC3 now and this is really confusing me.
I have a ViewModel that contains some child ViewModels. Each of the ChildViewModels get rendered with a different Partial View, and when submitting execute a different action on the Controller. All the ChildViewModels should perform some custom validation on their data, and if successful it should move on to the next page. If the validation fails, it should simply return to the ParentView and display the errors.
[HandleError]
public class MyController: Controller
{
public ActionResult Index()
{
var viewModel = new ParentViewModel();
return View("ParentView", viewModel);
}
[HttpPost]
public ActionResult ChildViewModelB_Action(ChildViewModelB viewModel)
{
if (ModelState.IsValid)
{
return View("ChildViewModelB_Page2", viewModel);
}
else
{
// I'm having trouble returning to the ParentView and
// simply displaying the ChildViewModel's errors, however
// discovered that creating a new copy of the VM and displaying
// the ParentView again shows the existing data and any errors
// But why??
var vm = new ParentViewModel();
return View("ParentView", vm);
}
}
}
For example,
The page loads with 3 options.
User selects option B and fills out a form.
Upon submit, the child ViewModel B gets validated and fails.
Page returns to ParentView, with ChildB all filled out, however ChildB errors are now also showing.
Why does creating a new copy of the ParentViewModel display the ParentView with the same data as the original ParentViewModel?
And is there a different way I should be returning to the ParentView after doing server-side validation?
You need to clear the modelstate if you intend to modify values in your POST action
else
{
ModelState.Clear();
var vm = new ParentViewModel();
return View("ParentView", vm);
}
The reason for that is because Html helper such as TextBoxFor will first look in the modelstate when binding their values and after that in the model. And since the modelstate already contains the POSTed values, that's what's used => the model is ignored. This is by design.
This being said the correct thing to do in your case is to simply redirect to the GET action which already blanks the model and respect the Redirect-After-Post pattern:
else
{
return RedirectToAction("Index");
}
Why does creating a new copy of the ParentViewModel display the
ParentView with the same data as the original ParentViewModel?
Because the values of the fields are retrieved from the POSTed form and not from the model. That makes sense right? We don't want the user to show a form filled with different values from what they submitted.

Resources