I am new to ASP.NET MVC 3, coming from RoR so I am somewhat familiar with the MVC design pattern.
I created a method that generates a select list to be used in a dropdownfor().
What I have below works but I was wondering if I can make it more efficient or at least do the same thing with less code?
Thanks
public static IEnumerable<SelectListItem> GetDistanceUnits(string distanceUnit)
{
DistanceUnit MilesUnit = new DistanceUnit();
MilesUnit.OptionValue = "mi";
MilesUnit.OptionName = "Miles";
MilesUnit.OptionSelected = "";
DistanceUnit KilometersUnit = new DistanceUnit();
KilometersUnit.OptionValue = "km";
KilometersUnit.OptionName = "Kilometers";
KilometersUnit.OptionSelected = "";
var distanceUnitList = new List<SelectListItem>();
distanceUnitList.Add(new SelectListItem
{
Value = MilesUnit.OptionValue,
Text = MilesUnit.OptionName,
Selected = MilesUnit.OptionSelected == distanceUnit
});
distanceUnitList.Add(new SelectListItem
{
Value = KilometersUnit.OptionValue,
Text = KilometersUnit.OptionName,
Selected = KilometersUnit.OptionSelected == distanceUnit
});
return distanceUnitList.OrderByAscending(c => c.Text);
}
You can use a generator to create your list and a little Linq to project the list.
public static IEnumerable<SelectListItem> GetDistanceUnits(string distanceUnit)
{
var distanceUnitList = GetUnits()
.Select(u =>
new SelectListItem
{
Value = u.OptionValue,
Text = u.OptionName,
Selected = u.OptionSelected == distanceUnit
})
.OrderByAscending(c => c.Text)
.ToList();
return distanceUnitList;
}
private static IEnumerable<DistanceUnit> GetUnits()
{
yield return new DistanceUnit
{
OptionValue = "mi";
OptionName = "Miles";
OptionSelected = "";
};
yield return new DistanceUnit
{
OptionValue = "km";
OptionName = "Kilometers";
OptionSelected = "";
};
}
You can condense the code a little bit more by using a list initializer like this:
var distanceUnitList = new List<SelectListItem> {
new SelectListItem {
Value = MilesUnit.OptionValue,
Text = MilesUnit.OptionName,
Selected = MilesUnit.OptionSelected == distanceUnit
},
new SelectListItem {
Value = KilometersUnit.OptionValue,
Text = KilometersUnit.OptionName,
Selected = KilometersUnit.OptionSelected == distanceUnit
}
};
Otherwise I'd say that's a pretty compact method, nicely organized, and will be very reusable in other areas of your MVC application.
You could make it with a little less code, but I am not sure how much more efficient it would be:
var distanceUnitList = new List<SelectListItem>
{
new SelectListItem{...},
new SelectListItem{...},
};
If you are going to use those local variables only once (to supply data to the SelectListItem), you don't need them. You can do the following:
var distanceUnitList = new List<SelectListItem>() {
new SelectListItem
{
Value = "mi",
Text = "Miles",
Selected = ("" == distanceUnit) // odd code...
},
new SelectListItem
{
Value = "km",
Text = "Kilometers",
Selected = ("" == distanceUnit)
}
};
Related
I have string value like below example for fax
string fax="1111111111";
I need below result for above string to add special character for fax format like below.
(111)-111-1111
my code for reference because my question going down please help any to get result
var list = (dynamic)null;
if (!String.IsNullOrEmpty(faxdos.medicalRecordsFax) && !String.IsNullOrEmpty(faxdos.fax))
{
list = new List<SelectListItem>
{
new SelectListItem{ Text=String.Format("{0:(###)-###-####}", faxdos.medicalRecordsFax)+" - Medical Records Fax", Value = faxdos.medicalRecordsFax},
new SelectListItem{ Text=String.Format("{0:(###)-###-####}", faxdos.fax), Value = faxdos.fax },
};
}
else if (!String.IsNullOrEmpty(faxdos.medicalRecordsFax))
{
list = new List<SelectListItem>
{
new SelectListItem{ Text=String.Format("{0:(###)-###-####}", faxdos.medicalRecordsFax)+" - Medical Records Fax", Value = faxdos.medicalRecordsFax},
};
}
else if (!String.IsNullOrEmpty(faxdos.fax))
{
list = new List<SelectListItem>
{
new SelectListItem{ Text=String.Format("{0:(###)-###-####}", faxdos.fax), Value = faxdos.fax },
};
}
else
{
list = new List<SelectListItem>
{
new SelectListItem{ Text="", Value = "" },
};
}
// ViewBag.emp = list;
var result = new SelectList(list, "Text", "Value");
return Json(result, JsonRequestBehavior.AllowGet);
well how about just writing code to do it
string fax="1111111111";
string str2 = $"({fax.Substring(0,3)})-{fax.SubString(3,3)}-{fax.Substring(6,4)}";
If you want to use the var result = string.Format("{0:(###)-###-####}", someValue) formatting mechanism, then the value you are formatting needs to be a number, not a string. So you could do something like this:
var telNoString = "1111111111";
if (long.TryParse(telNoString, out var telno))
{
var result = string.Format("{0:(###)-###-####}", telno);
Debug.WriteLine(result);
}
Which will result in (111)-111-1111 in the debug console.
How can I make a blank default to be displayed like " " in this #Html.DropDownListFor.
I have tried the over-rides and they don't work for this.
HTML:
<td>#Html.DropDownListFor(o => o.TerminalsDDL, Model.TerminalsDDL, new { id = "ddlTerminalID", #class = "form-control align-middle" })</td>
Controller:
public ActionResult Index()
{
var model = TCBL.GetTerminalData();
return View(model);
}
//POST: TerminalCommand/Index
/*This function will insert a user selecter terminal command into the TerminalCommand table*/
public ActionResult AddTerminalCommand(AddTerminalCommandVM input)
{
TerminalCommand terminalCommand = new TerminalCommand();
terminalCommand.TerminalID = input.TerminalID;
terminalCommand.Command = input.CommandID;
terminalCommand.CommandValue = input.CommandValue;
TCBL.AddTerminalCommand(terminalCommand);
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "TerminalCommand");
return Json(new { Url = redirectUrl });
}
Data Layer:
/*Gets All termianls for the terminalsDDL and all terminal Cmds for Model.TerminalCommands*/
public TerminalCommandVM GetTerminalData()
{
TerminalCommandVM terminals = new TerminalCommandVM();
//For Terminal drop downs
terminals.TerminalsDDL = TCDA.GetTerminalsDropDown();
//For terminal cmd lists
terminals.TerminalCommands = TCDA.GetAll();
//For helpdescription
terminals.HelpDescriptions = TCDA.GetAllHelpDescriptionValues();
terminals.HelpDescriptionID = TCDA.GetAllHelpDescriptionIDs();
//For TerminalCommandLookupsDDL
List<SelectListItem> terminalCommandLookups = new List<SelectListItem>();
var terminalCommandLookupsResults = TCDA.GetAllTerminalCommandLookups().OrderBy(o => o.Name); //.Where(x => x.Name.Contains("S3"));
if (terminalCommandLookupsResults != null)
{
foreach (var item in terminalCommandLookupsResults)
{
SelectListItem newItem = new SelectListItem();
newItem.Text = item.Name;
newItem.Value = item.ID.ToString();
terminalCommandLookups.Add(newItem);
}
}
var terminalCommandValues = TCDA.GetAllTerminalCommandValues();
terminals.TerminalCommandValues = terminalCommandValues;
terminals.TerminalCommandLookupsDDL = terminalCommandLookups;
return terminals;
}
Bottom is data access layer, where the CA gets the data for display. I believe HTML should have some sort of default blank selection though..
You can add a blank default before the for loop in your Data Layer
SelectListItem newItem = new SelectListItem();
newItem.Text = "";
newItem.Value = "";
terminalCommandLookups.Add(newItem);
you can use this overload of Dropdownlistfor -
Html.DropDownListFor(Expression<Func<dynamic,TProperty>> expression, IEnumerable<SelectLestItem> selectList, string optionLabel, object htmlAttributes)
like this
<td>#Html.DropDownListFor(o => o.TerminalsDDL, Model.TerminalsDDL,"", new { id = "ddlTerminalID", #class = "form-control align-middle" })</td>
I have a search method that queries Solr for event items. I need to modify it to only get events where the date has not already passed (i.e. Where(x => x.EventDate.Date >= DateTime.Now.Date), but I'm not sure how to add this because I'm not very familiar with Solr. Here's my search function:
public SearchQueryResults Search(string keywords, int page,int perPage, List<Guid> contentTypeFilters, List<Guid> otherFilters, ISortBuilder<SearchResultItem> sortBuilder)
{
var searchFilters = new List<IPredicateBuilder<SearchResultItem>>()
{
new IsSearchablePredicateBuilder()
};
if (contentTypeFilters.Any())
{
var contentTypePredicateBuilder = new ContentTypePredicateBuilder();
contentTypePredicateBuilder.ContentTypes = contentTypeFilters;
searchFilters.Add(contentTypePredicateBuilder);
}
if (otherFilters.Any())
{
var tagFilterBuilder = new TagsAndPredicateBuilder(otherFilters,_sitecoreContext);
searchFilters.Add(tagFilterBuilder);
}
if (string.IsNullOrWhiteSpace(keywords))
{
keywords = "";
}
SearchRequest searchRequest = new SearchRequest();
var queryParams = new Dictionary<string, string>() { };
queryParams.Add("q", keywords);
searchRequest.QueryParameters = queryParams;
searchRequest.SortBy = "";
searchRequest.SortOrder = "";
SearchQuery<SearchResultItem> queryArguments = new SearchQuery<SearchResultItem>();
queryArguments.FilterBuilders = searchFilters;
queryArguments.Page = page;
queryArguments.PerPage = perPage;
queryArguments.FacetsBuilder = new SearchFacetBuilder<SearchResultItem>();
queryArguments.SearchRequest = searchRequest;
queryArguments.IndexName = _indexName;
if (string.IsNullOrWhiteSpace(keywords))
{
queryArguments.QueryBuilders =new List<IPredicateBuilder<SearchResultItem>>();
}
else
{
queryArguments.QueryBuilders = new[] { new KeywordPredicateBuilder<SearchResultItem>(new[] { keywords }) };
}
queryArguments.SortBuilder = sortBuilder;
try
{
var results = _searchManager.GetResults<SearchResultItem>(queryArguments);
SearchQueryResults queryResults = new SearchQueryResults();
queryResults.ResultItems = results.Results;
queryResults.CurrentPage = page;
queryResults.TotalResults = Int32.Parse(results.TotalResults.ToString());
queryResults.TotalPages = (queryResults.TotalResults + perPage - 1) / perPage; ;
return queryResults;
}
catch (Exception exc)
{
Sitecore.Diagnostics.Log.Error("Error with FilteredSearch, could be a loss of connection to the SOLR server: " + exc.Message, this);
return null;
}
}
and here is how it's being called:
Results = _searchService.Search(searchTerm, CurrentPage - 1, 10, contentTypes, searchFilters,
new GenericSortBuilder<SearchResultItem>(q => q.OrderByDescending(r => r.SearchDate)));
How do I add in date filtering so that it only returns items where the date is in the future?
I would add filter query to the list of existing ones filtering the date field. On the documentation page, I was able to find information about fluent API, which could help here
Query.Field("date").From(DateTime.Now)
I'm not C# developer, that this code could have some mistakes, but I think the main idea is clear what needs to be done.
I am experimenting with the <optgroup> element and am trying to make several items belong to the same optgroup.
My code:
public async Task<ActionResult> GetStatsView()
{
var users = await _administrationServiceAPI.GetPersons();
var tanks = await _administrationServiceAPI.GetTanks();
var list = new List<SelectListItem>();
foreach (var u in users.Payload)
{
SelectListItem item = new SelectListItem {Text = u.Name, Value = u.Id.ToString(), Group = new SelectListGroup {Name = "Users"} };
list.Add(item);
}
foreach (var u in tanks.Payload)
{
SelectListItem item = new SelectListItem { Text = u.Name, Value = u.Id.ToString(), Group = new SelectListGroup { Name = "Tanks" } };
list.Add(item);
}
#ViewBag.MyList = list;
return View("StatsView");
}
view:
#Html.DropDownList("MyList")
result:
Desiered result is:
Users
UserName
UserName
UserName
Tanks
Tank
Tank
Tank
How do I do this?
To make it work, you need to reuse the SelectListGroup. Just use it like this:
var usersGroup = new SelectListGroup {Name = "Users"};
foreach (var u in users.Payload)
{
SelectListItem item = new SelectListItem {Text = u.Name, Value = u.Id.ToString(), Group = usersGroup };
list.Add(item);
}
And of course similarly for Tanks.
It does not matter that the name is the same, an instance used must be the same in various items to group them into single optgroup.
I'm searching a sorted dictionary with a key of type datetime and values as list of objects. What I need to find is the latest value(based on a property on the object) for each object in the dictionary. My object has 3 properties : a name, a value and a date when it was created. My dictionary is sorted by latest date in descending order.
I have got this working somehow, but I'm sure there is a shortcut for this using LINQ. Please note that I'm using .NET 3.5. Could you please help? Please dont get put off by the huge amount code below as I have added it for clarity and i'm only looking for a linq query to query inside a list of list objects.
Code below:
public void Should_link_recent_data_together()
{
var data = TimeSeriesDataFactoryEx.GetData();
var allAttributes = new List<string>()
{
TimeSeriesConstants.TOTAL_COST_CODE,
TimeSeriesConstants.TOTAL_VALUE_CODE,
TimeSeriesConstants.SOURCE_CODE
};
var latestList = new List<TimeSeries>();
var allValues = data.Values.ToList();
#region HOW DO I DO THIS USING LINQ?
bool found = false;
foreach (var attribute in allAttributes)
{
found = false;
foreach (var tsData in allValues)
{
foreach (var ts in tsData)
{
if (ts.MetricName == attribute && !string.IsNullOrEmpty(ts.MetricValue))
{
latestList.Add(ts);
found = true;
break;
}
}
if (found)
break;
}
}
#endregion
Assert.IsTrue(latestList.Count == 3);
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.TOTAL_COST_CODE).First().MetricValue == "1");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.TOTAL_VALUE_CODE).First().MetricValue == "2");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.SOURCE_CODE).First().MetricValue == "gp");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.SOURCE_CODE).First().Quarter == DateTime.Today.AddMonths(-3));
}
internal class TimeSeriesDataFactoryEx
{
public static SortedDictionary<DateTime?,List<TimeSeries>> GetData()
{
return new SortedDictionary<DateTime?, List<TimeSeries>>(new DateComparer())
{
{
DateTime.Today, new List<TimeSeries>()
{
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "1",
MetricName = TimeSeriesConstants.TOTAL_COST_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "2",
MetricName = TimeSeriesConstants.TOTAL_VALUE_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "",
MetricName = TimeSeriesConstants.SOURCE_CODE
}
}
},
{
DateTime.Today.AddMonths(-3), new List<TimeSeries>()
{
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "3",
MetricName = TimeSeriesConstants.TOTAL_COST_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "4",
MetricName = TimeSeriesConstants.TOTAL_VALUE_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "gp",
MetricName =TimeSeriesConstants.SOURCE_CODE
}
}
}
};
}
}
So, assuming I understand your question right, say you have a dictionary like so:
{ Key = "1/1/1900", Value = List Of Objects, of which each has a DateTimeProperty }
...
{ Key = "1/4/1900", Value = List Of Objects, of which each has a DateTimeProperty }
And you are looking to find a set of objects from your dictionary, where it's the latest by time of each key, then you can do this pretty simply with linq:
var latestItems = data.SelectMany(kvp =>
kvp.Value.OrderByDescending(value => value.Quarter).Take(1)
);
This query finds the most recent object in each bucket and then returns that as a single set (not an enumerable of enumerables). You can change the selector inside the SelectMany to find elements in each set as much as you want, as long as you return an IEnumerable from that callback.