ASP.NET MVC: почему `ToMvcHtmlString` не является общедоступным?

Какое правильное использование области сеанса

blockquote>

Используйте его только для данных с областью сеанса, и ничего больше. Например, вошедший в систему пользователь, его настройки, выбранный язык и т. Д.

См. Также:


И каждый раз, когда я посещаю страницу, список продуктов будет создан из последних записей в базе данных. Как я могу справиться с этим?

blockquote>

Обычно для этого используется область запроса или представления. Загрузка списка должна выполняться по методу @PostConstruct. Если страница не содержит , то область запроса будет прекрасной. Объект, обработанный представлением, будет вести себя как область запроса, если в любом случае нет .

Все ссылки «Просмотреть продукт» и «редактировать товар», которые только извлекают информацию (т.е. идемпотент), должны быть просто GET / , в которые вы проходите идентификатор объекта как параметр запроса по .

Все ссылки «delete product» и «save product» / кнопки, которые будут обрабатывать информацию (т.е. не-идемпотент), должны выполнять POST с помощью / (вы не хотите, чтобы они были заклассифицированы / searchbot-indexable!). Это, в свою очередь, требует . Чтобы сохранить данные для валидаций и ajax-запросов (так что вам не нужно перезагружать / preinitialize сущность при каждом запросе), компонент должен быть предпочтительно областью видимости.

Обратите внимание, что в каждом представлении вы должны иметь отдельный компонент, а также обратите внимание, что эти beans необязательно должны ссылаться друг на друга.

Итак, с учетом этого объекта «продукта» :

@Entity
public class Product {

    @Id
    private Long id;
    private String name;
    private String description;

    // ...
}

И этот «сервисный сервис» EJB:

@Stateless
public class ProductService {

    @PersistenceContext
    private EntityManager em;

    public Product find(Long id) {
        return em.find(Product.class, id);
    }

    public List list() {
        return em.createQuery("SELECT p FROM Product p", Product.class).getResultList();
    }

    public void create(Product product) {
        em.persist(product);
    }

    public void update(Product product) {
        em.merge(product);
    }

    public void delete(Product product) {
        em.remove(em.contains(product) ? product : em.merge(product));
    }

    // ...
}

Вы можете использовать этот «просмотр продуктов» на /products.xhtml:


    #{product.id}
    #{product.name}
    #{product.description}
    
        
            
        
    

@Named
@RequestScoped
public class ViewProducts {

    private List products; // +getter

    @EJB
    private ProductService productService;

    @PostConstruct
    public void init() {
        products = productService.list();
    }

    // ...
}

И вы можете получить этот «продукт редактирования» на /products/edit.xhtml:


    





    
    ...
    

@Named
@ViewScoped
public class EditProduct {

    private Product product; // +getter +setter

    @EJB
    private ProductService productService;

    public String save() {
        productService.save(product);
        return "/products?faces-redirect=true";
    }

    // ...
}

И этот преобразователь для для «edit product»:

@Named
@RequestScoped
public class ProductConverter implements Converter {

    @EJB
    private ProductService productService;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }

        try {
            Long id = Long.valueOf(value);
            return productService.find(id);
        } catch (NumberFormatException e) {
            throw new ConverterException("The value is not a valid Product ID: " + value, e);
        }
    }

    @Override    
    public String getAsString(FacesContext context, UIComponent component, Object value) {        
        if (value == null) {
            return "";
        }

        if (value instanceof Product) {
            Long id = ((Product) value).getId();
            return (id != null) ? String.valueOf(id) : null;
        } else {
            throw new ConverterException("The value is not a valid Product instance: " + value);
        }
    }

}

См. также:

18
задан Community 23 May 2017 в 12:25
поделиться

3 ответа

Я предполагаю, что побуду вас использовать вместо этого System.Web.HtmlString . Но да, я сам задавался этим вопросом, и я написал дублирующее расширение ToMvcHtmlString в своих помощниках.

MvcHtmlString - это, IIRC, просто исправление совместимости, поэтому MVC 2 может работать как на .NET 3.5, так и на 4, но даже в этом случае было бы полезно использовать для этого в вашем собственном коде.

8
ответ дан 30 November 2019 в 07:22
поделиться

Решает ли это вашу проблему?

public static MvcHtmlString SuperDenizControl(this HtmlHelper html)
{
    var builder = new TagBuilder("select");
    //blah blah blah amazing control
    var control = builder.ToString();
    return MvcHtmlString.Create(control);
}
5
ответ дан 30 November 2019 в 07:22
поделиться

Я подумал, что опубликую простой обходной путь для тех, кто может его искать и наткнуться на этот вопрос.

Хотя ToMvcHtmlString является внутренним, его довольно легко обойти, поскольку он использует общедоступные методы:

Из источника MVC:

internal MvcHtmlString ToMvcHtmlString(TagRenderMode renderMode) {
    return MvcHtmlString.Create(ToString(renderMode));
}

MvcHtmlString.Create и TagBuilder.ToString являются общедоступными, поэтому просто замените

return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);

на

return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));

и все готово! У меня отлично работает. Не уверен, почему они вообще потрудились сделать отдельный внутренний метод.

24
ответ дан 30 November 2019 в 07:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: